ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Oracle PL/SQL 游标循环,用 TaoToken 接入的 Codex 对照 %found 与 %rowcount

Oracle PL/SQL 游标循环,用 TaoToken 接入的 Codex 对照 %found 与 %rowcount 1. 为什么你的 PL/SQL 游标循环总是差一行数据如果你正在学 Oracle PL/SQL大概率绕不开显示游标、隐式游标和游标循环这三块。很多人第一次写while cur_orderinfo%found loop的时候都会遇到同一个现象明明表里有 5 条订单dbms_output只打印了 4 条最后一条永远消失。或者反过来循环停不下来SQL*Plus 里刷屏刷到只能按 CtrlC。还有人把%rowcount和sql%rowcount混着用结果统计出来的行数对不上。这些问题的根子不在 Oracle而在于游标四步声明、open、fetch、close里 fetch 的时机、%found的判断位置、以及异常分支里有没有 close。这篇就按「先跑通一个能对照代码的 AI 通道再逐行拆解游标逻辑」的顺序来写。我会用 TaoToken 接入的 Codex 作为对照工具让它帮我逐行解释cur_orderinfo那段示例里每个属性的判断时机同时检查那段 while 循环有没有漏 fetch、exception 里是不是只打印了「错误」却没关游标。TaoToken 在这里只做两件事提供一把 Key 和一个兼容通道真正的 PL/SQL 逻辑还是你在 SQL*Plus 里执行、由 Codex 辅助对照。适合谁看刚学 PL/SQL 游标、被%found和%rowcount绕晕、想找个能逐行讲代码的工具来对照排查的初学者。读完你能自己判断一段游标循环到底哪里写错了也能用 Codex 把隐式游标和 for 循环游标的差异问清楚。2. 前置准备用 TaoToken 拿到 Key 并配通 Codex这一步只做通道不碰 PL/SQL 逻辑。先打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建一把 API Key。创建完之后把 Codex 的 Base URL 填成https://taotoken.net/api注意不要带/v1也不要填官网地址。Key 就用刚创建的那把同一把 Key 跑通一次问答就算通道验证完成。配置的时候有几个细节容易踩Base URL 必须是https://taotoken.net/api多一个斜杠或者少一个斜杠都可能让请求 404。Key 的权限确认是默认的对话权限即可不需要额外开什么。如果你用的是环境变量方式可以这样写export OPENAI_BASE_URLhttps://taotoken.net/api export OPENAI_API_KEY你创建的那把Key配好之后先跑一次最简单的问答确认通道是通的。比如直接问一句「Oracle 显示游标 open 之后必须 fetch 吗」能正常返回就说明 Key 和 Base URL 都没问题。跑通之后可以到 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 看一下调用是否成功确认用量记录里有这次请求。这一步的意义在于后面我要让 Codex 逐行对照cur_orderinfo那段代码如果通道没通对照就无从谈起。通道只负责把问题送出去、把解释拿回来PL/SQL 的执行结果仍然以你本地 SQL*Plus 的输出为准。3. 可复制配置把 cur_orderinfo 示例喂给 Codex 逐行对照通道通了之后把原文那段cur_orderinfo示例整理成一段干净的代码连同你的问题一起发给 Codex。我建议按下面这个模板来问这样它返回的解释会贴着你的代码走而不是泛泛讲概念。set serveroutput on declare cursor cur_orderinfo (username in varchar2) is select * from orderinfo where username username; var_orderinfo orderinfo%rowtype; begin open cur_orderinfo(abcd); fetch cur_orderinfo into var_orderinfo; while cur_orderinfo%found loop dbms_output.put_line(订单编号 || var_orderinfo.ordercode); fetch cur_orderinfo into var_orderinfo; end loop; close cur_orderinfo; exception when others then dbms_output.put_line(错误); end; /发给 Codex 的问题可以这样写请逐行解释这段 PL/SQL 里%found、%notfound、%isopen、%rowcount分别在什么时机被判断为什么while cur_orderinfo%found loop里要在循环体末尾再 fetch 一次如果只在循环开头 fetch 会怎样。另外检查 exception 分支里只打印「错误」而没 close 游标会有什么后果。Codex 返回的解释里有几个点你要重点核对。第一%found在fetch之后才有意义open之后直接判断%found是未定义行为。第二循环体末尾那次fetch是为了把「下一条」读进来让下一轮while判断时%found反映的是新记录是否存在。第三如果只在循环开头 fetch第一次进入循环时%found还是上一次 fetch 的结果会导致最后一条记录被重复打印或者循环提前退出。第四exception 里不 close 游标游标会一直占着内存和打开句柄直到会话结束。你可以让 Codex 把%rowcount也加进去对照。比如在循环里加一行dbms_output.put_line(已处理 || cur_orderinfo%rowcount);然后问它%rowcount在 fetch 之后的值代表什么。它会告诉你%rowcount返回的是到目前为止 fetch 成功的行数而不是结果集总行数。这一点和sql%rowcount完全不同后者是隐式游标属性返回的是最近一条 DML 语句影响的行数。4. 验证请求跑通一次对照并看调用是否成功配置好之后实际发一次请求确认 Codex 能返回针对cur_orderinfo的逐行解释。请求发出去之后到 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 看调用记录确认这次请求状态是成功的。如果返回内容里明确提到了%found的判断时机、循环内 fetch 的位置、以及 exception 未 close 的问题说明对照通道已经跑通。跑通之后你可以继续用同一把 Key 问隐式游标和 for 循环游标的问题。比如把原文那段sql%notfound的 update 示例发过去问它sql%notfound在 update 影响 0 行时返回什么、影响多行时返回什么。再比如把 for 循环游标的两种写法发过去问它为什么 for 循环不用手动 open、fetch、close。这里有个实测下来很省事的做法让 Codex 把显示游标、隐式游标、for 循环游标三种写法的属性对照做成一张表你直接拿这张表去核对原文里的每个示例。表格大概长这样属性显示游标隐式游标for 循环游标%foundfetch 后判断sql%found循环内自动判断%notfoundfetch 后判断sql%notfound循环结束条件%rowcount已 fetch 行数最近 DML 影响行数当前循环第几行%isopenopen 后 true总是 false不用判断这张表能帮你快速分清%rowcount和sql%rowcount的区别也能解释为什么 for 循环游标里写%isopen没有意义。5. 本篇常见错排查漏 fetch、死循环、属性混用5.1 漏掉最后一次 fetch 导致少一行最常见的错误就是循环体里忘了再 fetch 一次。原文那段while cur_orderinfo%found loop里循环体末尾有一句fetch cur_orderinfo into var_orderinfo;这句不能省。如果你只在open之后 fetch 一次然后进循环打印打印完不 fetch 就回到while判断%found还是上一次的结果循环会一直打印同一条记录变成死循环。反过来如果你在循环开头 fetch循环体末尾不 fetch那么第一次进入循环时%found反映的是 open 后那次 fetch 的结果打印的是第一条第二次进入循环时%found还是第一条的结果但var_orderinfo已经被循环开头的 fetch 覆盖成第二条了于是打印第二条……直到最后一次循环开头的 fetch 失败%found变 false循环退出但最后一条已经打印过了看起来没漏。真正会漏的是另一种写法open 后不 fetch直接 while 判断这时%found未定义行为不可预测。5.2 把 %found 循环写成死循环死循环的典型写法是循环体里没有 fetch或者 fetch 写在了if分支里导致某些路径不执行。还有一种是把%found写成了%notfound逻辑反了。排查的时候在循环里加一行dbms_output.put_line(rowcount || cur_orderinfo%rowcount);如果这个数字一直不涨说明 fetch 没生效或者没执行。5.3 分不清 %rowcount 与 sql%rowcountcur_orderinfo%rowcount是显示游标属性返回的是这个游标已经 fetch 成功的行数。sql%rowcount是隐式游标属性返回的是最近一条 insert、update、delete 影响的行数。原文那段 update 示例里用sql%notfound判断「此用户不需要更新手机号码」就是因为 update 影响 0 行时sql%notfound为 true。如果你把sql%rowcount用在显示游标上会报错或者拿到不相关的值。5.4 exception 里只打印「错误」不关游标原文那段 exception 分支只写了dbms_output.put_line(错误);没有close cur_orderinfo;。如果 open 之后、close 之前抛了异常游标会一直保持打开状态。短会话里可能看不出问题但长会话或者循环调用里打开游标数会累积最终触发ORA-01000: maximum open cursors exceeded。正确的做法是在 exception 里也 close或者用if cur_orderinfo%isopen then close cur_orderinfo; end if;包一层。5.5 for 循环游标为什么不用手动 open/closefor 循环游标是 Oracle 帮你做了 open、fetch、close 三件事。你只需要声明游标或者直接写子查询然后在 for 里遍历。循环变量var_orderinfo是自动声明的类型是%rowtype不用你手动定义。这也是为什么 for 循环游标里写%isopen没意义——循环开始前 Oracle 已经 open 了循环结束后 Oracle 已经 close 了你在循环体里判断%isopen永远是 true。6. 继续排查隐式游标和 for 循环游标显示游标那段对照跑通之后你可以用同一把 Key 继续问隐式游标和 for 循环游标的问题。隐式游标的关键是sql%notfound、sql%found、sql%rowcount这三个属性它们只在 DML 语句之后有意义而且sql%rowcount在 select into 之后也能用。for 循环游标的关键是「不用手动 open/close」和「循环变量自动声明」这两点。如果你打算长期用 Codex 辅助排查 PL/SQL可以考虑配通 Coding Plan这样在写存储过程、调试游标循环的时候能连续对话不用每次重新贴代码。接入文档在 https://taotoken.net/doc 可以查到 Base URL 和 Key 的详细配置方式API Keys 管理在 https://taotoken.net/api-keys 可以随时查看和轮换。模型对话入口在 https://taotoken.net/chat 可以直接试问答ClaudeCodeAnthropic 相关配置在 https://taotoken.net/claudecode-anthropic 有说明。最后留一个我踩过的坑在 SQL*Plus 里跑游标循环之前先set serveroutput on否则dbms_output.put_line的输出你看不到会误以为循环没执行。另外fetch失败时%found变 false但var_orderinfo里的值还是上一次的不要在循环外直接用这个变量。
返回列表