PL/SQL 存储过程错误处理,让 Codex 走 TaoToken 查格式

发布时间:2026/9/18 15:52:57
PL/SQL 存储过程错误处理,让 Codex 走 TaoToken 查格式 PL/SQL 存储过程错误处理里游标 obj 遍历 Sys_User、再调用 sys_User_API.Modify(param1,param2) 初始化密码是很多初学者的第一段真实业务代码我让 Codex 走 TaoToken 逐行解释Key 和 Base URL 从 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_content 拿。一旦某行 Modify 抛错外层 loop 直接断掉后面的用户全没跑到问题往往只是 begin…exception…end 包在 loop 外还是 loop 内。Codex 只做生成、解释、对照代码不连接 Oracle也不代替 SQL*Plus 执行真正跑存储过程、看 Dbms_Output 输出、把报错贴回对话仍然在读者自己的数据库会话里完成。下面按原文两个 PL/SQL 例子的顺序把“为什么会断”“该包哪一层”“怎么让 Codex 帮你查格式”“怎么在本地验证”拆开讲。1. 游标 obj 遍历 Sys_User 时为什么一行 Modify 出错就让整段停住1.1 先复现初学者最常写的无异常版本很多人的第一版长这样声明游标 obj从 Sys_User 取一批待初始化密码的用户loop fetch然后直接调用 sys_User_API.Modify(rec_.name, 初始密码)。代码看起来顺但异常处理完全没写。只要 Modify 内部因为某个用户的数据不满足约束而 raise控制流就不会回到 fetch 下一行而是直接跳出 loop游标后面的用户全部漏掉。SQL*Plus 里看到的就是一个 ORA 错误前面成功初始化的用户可能已经提交后面的却还没动数据状态一半一半。declare cursor obj is select name from Sys_User where 状态 待初始化; rec_ obj%rowtype; begin open obj; loop fetch obj into rec_; exit when obj%notfound; sys_User_API.Modify(rec_.name, 初始密码); end loop; close obj; end; /这段代码的问题不在游标也不在 Modify 的参数个数而在异常传播路径。PL/SQL 的异常如果没有在当前块被捕获会一层层往外抛外层没有 exception 分支时整个匿名块或存储过程就终止。loop 只是普通控制结构不会自动“跳过坏行”。所以初学者看到的现象是“只处理了前几个用户”本质是第一个异常把循环打断了。1.2 报错后 loop 断掉的真实原因异常向上抛把执行顺序画出来更清楚open obj 之后进入 loopfetch 拿到 rec_调用 Modify如果 Modify 内部 raise当前块没有 exception异常向上找。找不到就报错退出exit when 后面的 close obj 都未必执行。换句话说异常处理的边界决定了“坏一行”的影响力范围。边界在 loop 外坏一行影响整个循环边界在 loop 内坏一行只影响当前这一轮。原文两个例子之所以把初学者绕晕就是代码块层级看起来差不多执行结果却完全不同。这里还要提醒一句sys_User_API.Modify 如果是别人写的 API它内部可能已经 commit也可能没有。外层加 exception 只能让循环继续不能自动把 Modify 内部做了一半的事情回滚。要不要 savepoint、要不要 rollback、要不要记录错误用户是业务规则不是 PL/SQL 语法能替你决定的。Codex 可以帮你解释这些分支但最终策略仍要你自己在本地数据库里验证。1.3 给 Codex 的描述模板先把问题锁在“包错位置”上把代码贴给 Codex 之前描述越具体它越不会给你泛泛的语法讲义。可以这样写下面有一段 PL/SQL游标 obj 遍历 Sys_User循环调用 sys_User_API.Modify(rec_.name, 初始密码) 初始化密码。现在某一行 Modify 报错后外层 loop 直接退出我想知道 begin…exception…end 应该包在 loop 内还是 loop 外并请逐行对比两种写法。不要连接 Oracle只生成和解释代码。这样 Codex 会把注意力放在异常边界、fetch 顺序、close obj 位置和 Dbms_Output 输出上。2. 在 Codex 里走 TaoToken 查 PL/SQL 异常格式先拿 Key 再配 config.toml2.1 从官网注册并创建 YOUR_API_KEY先打开 TaoToken 注册账号进控制台创建 API Key。Key 不要写进文章、不要贴到公开仓库本文统一用 YOUR_API_KEY 占位。创建好之后在模型广场确认你要用的模型 ID不同模型、不同套餐的可用范围会变所以别抄别人截图里的 ID以 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_content 模型广场当时列表为准。TaoToken 在这里负责统一 API 通道、Key 和用量记录它不连接你的 Oracle也不会替你执行 SQL*Plus 命令。2.2 ~/.codex/config.toml 里把 provider 指向 https://taotoken.net/apiCodex 的配置写在 ~/.codex/config.toml。核心是 model、model_provider以及对应 provider 下的 base_url。Base URL 填 https://taotoken.net/api末尾不要加 /v1更不要把官网落地页的 utm_source 拼上去。Key 建议放环境变量再用 env_key 引用避免明文散落在配置里。下面是一份可复制的骨架YOUR_MODEL_ID 换成模型广场里真实可用的 ID。model YOUR_MODEL_ID model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chatmacOS 或 Linux 终端里可以这样导出 Keyexport TAOTOKEN_API_KEYYOUR_API_KEYWindows PowerShell 里对应写法$env:TAOTOKEN_API_KEYYOUR_API_KEY注意不要把 Claude Code 的 ANTHROPIC_BASE_URL、ANTHROPIC_AUTH_TOKEN 那一套套到 Codex 上。Codex 读的是自己的 config.toml 和 provider 配置混用变量只会让你在排障时多绕一圈。改完配置后重新开一个终端再启动 Codex。2.3 401 和 provider 不认时先查哪里配置完第一次调用最容易遇到两类问题。第一类是 401通常不是模型问题而是环境变量没生效、Key 复制时带了空格、或者终端窗口没有重启。第二类是 Codex 提示 provider 不存在或 base_url 读不到优先检查 config.toml 的层级model_provider 是否等于自定义 provider 的名字[model_providers.taotoken] 这一段有没有拼错base_url 是否误写成带 /v1 或带 UTM 的地址。真正的 Oracle 报错不在这里PL/SQL 的 ORA- 错误要在 SQL*Plus 里看不要指望 Codex 通道替你连库。3. 把 begin…exception…end 放进 loop 内Sys_User 初始化密码的对照写法3.1 错误示范异常处理包在 loop 外只会处理一次先看包在 loop 外的写法。外层 begin 里 open、loop、fetch、Modify最后在 loop 结束之后放 exception。这样写的效果是Modify 一旦抛错控制流立刻离开 loop跳到 exception后面的用户不会再被 fetch。即使 exception 里写了 Dbms_Output.put_line也只是打印一次循环已经结束。原文里初学者疑惑“为什么只有一个错误提示”原因就在这里。declare cursor obj is select name from Sys_User where 状态 待初始化; rec_ obj%rowtype; begin open obj; loop fetch obj into rec_; exit when obj%notfound; sys_User_API.Modify(rec_.name, 初始密码); end loop; close obj; exception when others then dbms_output.put_line(初始化用户密码出错 || sqlerrm); end; /这段代码不是“错在 exception 没写”而是“exception 的位置让 loop 无法继续”。它适合那种“只要有一条失败就整体停止”的业务。如果初始化密码要求每个用户独立处理一条失败不影响其他用户就要把异常边界缩小到 Modify 这一行周围。3.2 正确思路内层 begin 包住 sys_User_API.Modify外层 loop 继续正确写法是在 loop 里面再加一个 begin…exception…end把 sys_User_API.Modify 单独包起来。这样某一行失败时异常在内层被捕获内层打印错误用户和 SQLERRM然后控制流回到内层 end 后面的位置也就是继续执行下一次 fetch。外层 loop 不会被异常打断close obj 也能正常执行。Codex 建议你抄回本地的关键结构就是这段内层 begin、exception when others then、end;但具体参数和表名要按你的库改。declare cursor obj is select name from Sys_User where 状态 待初始化; rec_ obj%rowtype; begin open obj; loop fetch obj into rec_; exit when obj%notfound; begin sys_User_API.Modify(rec_.name, 初始密码); exception when others then dbms_output.put_line(初始化用户密码出错用户( || rec_.name || ) || sqlerrm); end; end loop; close obj; exception when others then dbms_output.put_line(游标遍历外层出错 || sqlerrm); if obj%isopen then close obj; end if; end; /这里保留外层 exception是为了处理 open、fetch、close 或其它非 Modify 异常。内层只兜住单行 Modify外层兜住游标级错误。如果业务要求失败行必须回滚而成功行必须保留还要看 sys_User_API.Modify 内部是否提交、是否需要 savepoint。可以先在测试库用少量用户试把失败用户的 name 和 sqlerrm 写进日志表再决定批量跑还是跳过。3.3 让 Codex 逐行解释两张代码的执行顺序拿到上面两个版本后可以把它们一起贴给 Codex并加一句请按行号说明第一版在 Modify 报错时哪些行不会执行第二版为什么能继续 fetch并指出 close obj 分别在哪些路径执行。Codex 走 TaoToken 消耗 Token 完成解释不需要它连数据库。这样的提问能迫使它对比异常边界而不是只背 when others 的语法。若你想继续对照其他存储过程错误处理格式也可以沿用同一模板贴脱敏代码、说清楚期望行为、要求逐行解释再把建议抄回本地 SQL*Plus 验证。3.4 在 SQL*Plus 里自己验证把 Dbms_Output 打开验证不要在对话里“模拟执行”而是在本地 SQLPlus 里打开输出先执行 set serveroutput on再运行匿名块。观察三件事报错用户有没有打印、后面的用户有没有继续处理、成功和失败各有多少条。如果 Dbms_Output 没有输出先确认 serveroutput 是否为 on再确认调用方没有把输出缓冲区吞掉。把 SQLPlus 的完整报错、打印结果、以及你用的测试数据贴回 Codex它才能继续帮你判断是异常边界问题还是 Modify 内部逻辑问题。生产库不要直接全量跑先用测试用户或 where 条件限制几条。4. 排障Codex 配置、PL/SQL 异常和 SQL*Plus 验证各自的坑4.1 Codex 侧Base URL 多了 /v1 或 Key 没加载Codex 侧最常见的排障点还是配置文件。base_url 只写 https://taotoken.net/api不要写成 https://taotoken.net/api/v1也不要把它和官网落地页混在一起。官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_content 是给人打开注册、创建 Key、看模型广场和看用量的填进工具的接口地址是 https://taotoken.net/api。若 Codex 报 401先 echo 一下环境变量确认 TAOTOKEN_API_KEY 有值若提示模型不存在回模型广场核对模型 ID不要自己拼日期后缀。4.2 PL/SQL 侧when others 吞错、没有回滚、游标没关PL/SQL 侧不要把 when others 当成万能胶。它能接住异常让循环继续但如果你只写 null错误就被吞掉后面查数据差异会很痛苦。至少把 rec_.name、sqlerrm、当前时间写进日志表或打印出来。还要考虑 Modify 内部的事务行为如果它已经提交了部分数据外层捕获异常并不会自动撤销。游标关闭也要注意内层异常处理不会关闭 obj外层 exception 里可以用 if obj%isopen then close obj; end if; 兜底。批量初始化密码前先备份或限制范围是最便宜的安全措施。4.3 验证侧SQL*Plus 里先小批量再对照 Codex 建议改写SQLPlus 验证时先用 where rownum 3 或某个测试部门限制数据量确认内层 begin…exception…end 真的能让 loop 继续。然后把 Codex 建议的 Dbms_Output.put_line(初始化用户密码出错用户( || rec_.name || )); 抄进内层异常跑一遍看输出是否符合预期。若失败用户被跳过但后续用户继续说明异常边界放对了若整个块停止说明 exception 还在 loop 外或者 Modify 的异常没有被内层捕获。把 SQLPlus 的结果贴回对话再让 Codex 对照下一段存储过程。5. 跑通之后别让 Key 和额度卡住对账与下一步5.1 去模型对话确认模型 ID 和 Base URLCodex 配置改完后不要直接拿一段大 PL/SQL 去试。先在 TaoToken 模型对话 用同一把 Key 发一条短消息确认模型 ID、Base URL、Key 三者能通。对话页能返回内容再回到 Codex 里问游标和异常处理如果对话页都不通问题就在 Key 或模型 ID不在 PL/SQL 代码。这样能把“通道问题”和“代码问题”分开排障快很多。5.2 去控制台看这次 Codex 调用有没有记上账模型对话通了以后再让 Codex 解释那两段游标遍历 Sys_User 的代码。解释完回到 控制台 API Keys 看这次调用有没有记上账顺便确认 Key 没有泄漏到公开仓库。若你准备长期用 Codex 对照存储过程、批量改写错误处理格式可以打开 Coding Plan 看套餐是否够用。模型 ID 仍以 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_content 模型广场当时列表为准不要照搬别人配置。5.3 下一步把内层异常模板套到其他存储过程这次的重点不是让 Codex 替你执行 Oracle而是让它帮你确认 begin…exception…end 的边界。内层包住单行业务调用外层包住游标和资源释放错误用户用 Dbms_Output 或日志表留下痕迹。拿到这个模板后你可以把其他存储过程里的循环调用逐个替换先脱敏贴给 Codex问清楚异常应该放哪一层再把建议抄回本地 SQL*Plus 跑小批量验证。Key 不够或模型要切换时回到 TaoToken 创建新的 YOUR_API_KEYBase URL 继续用 https://taotoken.net/api不要加 /v1也不要把官网 UTM 带进配置文件。这样下一段存储过程错误处理格式就能继续对照不会因为某一行 Modify 报错又把整个 loop 拖停。