在 Oracle 里维护证件脱敏函数DESEN_ID的人,大多踩过同一个坑:dbms_obfuscation_toolkit.md5在 12c 之后被标记为废弃,SUBSTRB按字节截断遇到中文姓名会切出半个字符,upper/lower的大小写转换顺序一旦写反,MD5 结果就和预期对不上。更麻烦的是,函数写完之后缺少快速验证手段——总不能每次都往生产表里插测试数据。这篇用 TaoToken 作为 Codex 的模型通道,把DESEN_ID的脱敏规则交给 Codex 生成测试数据和边界用例,跑通 MD5 拼接与 B99 分支的校验。TaoToken 官网入口:https://taotoken.net/?utm_source=taotoken_aicg_blog_end
一、原问题与场景:DESEN_ID 的三处易错点
先把这段存储过程的逻辑拆清楚。DESEN_ID接收两个入参:FIELDVALUETYPE(证件类型串)和FIELDVALUE(证件号码串),两者都用split函数拆成多行,再用游标cur_test做笛卡尔配对,逐条判断:
- 当
column_type != 'B99'且证件号非空且LENGTHb >= 14时,取证件号前 14 字节,拼接全文的 MD5(先upper再转 raw 做 md5,最后lower输出); - 当
column_type = 'B99'且证件号非空时,直接输出全文 MD5; - 其余情况原样保留。
拼接结果用逗号连接成RESU1返回。
三处易错点很具体。第一,dbms_obfuscation_toolkit.md5在 Oracle 12c 起废弃,虽然多数环境仍能调用,但新版本可能直接报PLS-00201: identifier 'DBMS_OBFUSCATION_TOOLKIT' must be declared,需要改用DBMS_CRYPTO.HASH配合UTL_RAW.CAST_TO_RAW。第二,SUBSTRB(c.column_value, 0, 14)是按字节截断,如果证件号前 14 字节里包含中文(比如姓名混入),会切出半个多字节字符,返回乱码。第三,MD5 前先upper再lower输出,这个大小写顺序是刻意的——先统一大写再算摘要,保证同一证件号不同大小写输入得到一致结果,写反了校验就对不上。
问题在于,这些边界光靠读代码很难确认。14 字节边界到底切在哪、B99 分支和普通分支的 MD5 是否一致、中文姓名参与时SUBSTRB的行为如何,都需要实际跑一遍。这就是本篇要解决的核心:用 Codex 生成测试数据并跑边界用例。
二、TaoToken 前置:给 Codex 配一条稳定的模型通道
Codex 本身是命令行编码代理,它需要一个可访问的模型后端。官方接口在部分网络环境下连接不稳定,本地模型又常常在长上下文和代码理解上力不从心。TaoToken 在这里的角色很单一:作为 Codex 的模型通道,解决"官方接口难连、本地模型不好使"的问题,不替代编辑器,也不参与代码生成逻辑本身。
操作路径是:打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 注册并创建一个 API Key,然后把 Codex 的 Base URL 指向https://taotoken.net/api。拿到 Key 之后,Codex 就能通过 TaoToken 访问模型,对DESEN_ID这段存储过程做快速校验。
需要提前准备的东西:
- 一个可用的 TaoToken API Key(形如
YOUR_API_KEY); - 本机已安装 Codex CLI;
- 一段待验证的
DESEN_ID函数源码,以及你期望的脱敏输出样例。
如果你还没创建 Key,可以直接去控制台的 API Keys 页面生成:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite
三、可复制配置:Codex 接入 TaoToken
Codex 的配置走config.toml,模型通道的关键是base_url和api_key两项。下面是一份可直接复制的配置片段,把YOUR_API_KEY替换成你自己的 Key 即可:
# ~/.codex/config.toml model = "gpt-5-codex" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "responses"对应的环境变量在 shell 里导出:
export TAOTOKEN_API_KEY="YOUR_API_KEY"如果你更习惯用 CLI 一次性拉起,也可以用 TaoToken 提供的命令行工具:
npm i -g @taotoken/taotoken taotoken cc -k YOUR_API_KEY -u https://taotoken.net/api -m gpt-5-codex配置完成后,Codex 的请求会经由https://taotoken.net/api转发到模型。这里要强调一点:TaoToken 只负责通道,DESEN_ID的脱敏规则、测试数据、边界用例都由你在 Codex 会话里给出,模型负责按规则生成 SQL 和断言。
四、验证请求与成功结果:让 Codex 跑边界用例
配置就绪后,进入 Codex 会话,把DESEN_ID函数源码粘贴进去,并附上明确的验证指令。指令要覆盖三类边界:
- 14 字节边界:构造长度恰好 14 字节、15 字节、13 字节的证件号,确认
LENGTHb >= 14的判断和SUBSTRB(..., 0, 14)的截断位置; - B99 分支:同一证件号分别以
B99和非B99类型传入,对比输出——非 B99 应是"前 14 字节 + MD5",B99 应只有 MD5; - 中文姓名:构造前 14 字节内含中文的证件号,观察
SUBSTRB是否切出乱码,以及 MD5 是否仍按全文计算。
一段可直接粘贴的验证提示词示例:
下面是一段 Oracle 存储过程 DESEN_ID,请帮我做三件事: 1. 按脱敏规则生成 6 组测试数据,覆盖 14 字节边界(13/14/15 字节)、B99 分支、中文姓名; 2. 对每组数据手算出期望输出,说明 MD5 拼接部分; 3. 给出可在 Oracle 里直接执行的匿名块,调用 DESEN_ID 并打印实际输出,方便我对比。 注意:MD5 计算前先 upper 再转 raw,输出 lower;非 B99 取前 14 字节拼接。Codex 返回的结果里,你会拿到一份测试数据表和对应的匿名块。把它贴进 SQL*Plus 或 SQL Developer 执行,重点看三件事:
- 13 字节的证件号是否走了
else分支原样返回; - 14 字节和 15 字节的证件号,前 14 字节是否一致、MD5 是否按全文计算;
- B99 分支的输出是否等于非 B99 分支输出中 MD5 的那一段。
如果实际输出和手算期望一致,说明DESEN_ID的 MD5 拼接和分支逻辑符合预期。这一步的成功标志很明确:匿名块执行无报错,且每组数据的实际输出与期望输出逐字符相等。
五、本篇常见错排查
跑验证的过程中,下面几类报错出现频率最高,按现象对号入座即可。
PLS-00201: identifier 'DBMS_OBFUSCATION_TOOLKIT' must be declared
这是 12c 之后废弃导致的。两种处理方式:一是确认当前用户有该包的执行权限(GRANT EXECUTE ON DBMS_OBFUSCATION_TOOLKIT TO 用户名),二是改用DBMS_CRYPTO.HASH。用DBMS_CRYPTO时注意入参是RAW类型,需要UTL_RAW.CAST_TO_RAW转换,且哈希类型用DBMS_CRYPTO.HASH_MD5:
MD5VALUE := LOWER(RAWTOHEX(DBMS_CRYPTO.HASH( UTL_RAW.CAST_TO_RAW(UPPER(c.column_value)), DBMS_CRYPTO.HASH_MD5)));SUBSTRB 截断出乱码
SUBSTRB按字节截断,中文在 UTF-8 下占 3 字节,前 14 字节很可能切在字符中间。如果业务上证件号本身是纯 ASCII(身份证号、护照号通常如此),这个问题不会暴露;但一旦有中文混入,就需要改用SUBSTR(按字符)或先做字符集校验。验证时专门构造含中文的用例,就是为了把这个隐患提前暴露出来。
MD5 大小写对不上
upper和lower的顺序不能反。正确顺序是:先UPPER统一大小写,再CAST_TO_RAW,再算 MD5,最后LOWER输出十六进制。如果先LOWER再算,同一证件号的大小写变体就会得到不同摘要,校验必然失败。
游标配对结果为空
cur_test用split(FIELDVALUE)和split(FIELDVALUETYPE)做笛卡尔积,如果两个入参的拆分元素数量不一致,配对结果会多出或缺失。验证时确保两个入参的元素个数相同,否则RESU1的逗号拼接顺序会和预期不符。
Codex 会话里模型无响应
先确认TAOTOKEN_API_KEY环境变量已导出,再确认config.toml里base_url是https://taotoken.net/api(注意不要多加路径)。如果仍不通,去 API Keys 页面确认 Key 状态正常:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite
六、语义一致 CTA
本篇的主线是"验证用量":用 Codex 通过 TaoToken 通道,对DESEN_ID的 MD5 拼接、14 字节截断、B99 分支做快速校验。如果你后续要把这类验证固化成日常流程,或者让 Codex 长期参与存储过程的边界测试,可以考虑 Coding Plan,把模型调用额度稳定下来:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite
接入配置和报错排查的完整说明在接入文档里:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite
想直接在网页里对模型发起验证对话,用模型对话入口:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite
如果你用的是 Claude Code 而非 Codex,配置走settings.json里的ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY,把 Base URL 指向https://taotoken.net/api即可,参考:https://taotoken.net/claude-code?utm_source=taotoken_aicg_blog_end&utm_content=claudecode&utm_campaign=rewrite