varchar、nvarchar 清空格游标拼动态 UPDATE 最容易漏字段。原文脚本 from sysobjects join syscolumns、xtype in (167,175)、nvarchar(500) 拼 exec跑完总有表没动静。TaoToken 在 Codex 里只负责对话通道先打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 建 Key再把 Base URL 填成 https://taotoken.net/api。UPDATE 该在本地 SSMS 执行的仍在本地执行。那个脚本的问题不止一处。类型判断用的是数字 xtype167 是 varchar175 是 char也就是说 nvarchar(231) 和 nchar(239) 从一开始就没进游标s 只给了 nvarchar(500)表名一长拼接就被截断exec 直接报语法错而游标没检查 error 继续往下 fetch于是变成静默跳过列名是手写方括号拼的遇到名字里带]的列直接拼坏。这三类漏靠肉眼看脚本很难看全把它连同报错一起丢给 Codex 逐行对照才划算。1. 游标跑完还有空格先把三类漏分清楚原文那段脚本压缩成一行实际丢进 SSMS 连语法都过不去——declare s nvarchar(500) declare c cursor for中间没有语句结束符。这只是表面报错真正让字段没清干净的是下面三层逻辑问题。先看清是哪一类再去问 Codex问出来的答案才有用。1.1 xtype in (167,175) 从类型上就漏了 nvarchar很多人记 xtype 数值靠猜这里直接给对照表。旧目录视图 syscolumns 的 xtype 和类型名的关系是固定的不会因为数据库版本变类型名syscolumns.xtype能否用 LTRIM/RTRIM 处理varchar167可以char175可以nvarchar231可以nchar239可以text35不建议直接套ntext99不建议直接套原文写的是in(167,175)正好等于 varchar char 这两个。标题喊着要去 varchar、nvarchar 的空格代码却把 nvarchar 排除在外这类偏差就是跑完还有空格最直接的来源。稳妥的写法是别硬编码数字改用sys.types按类型名过滤或者至少把条件补成in(167,175,231,239)。1.2 s 只有 nvarchar(500)长表名拼接会被截断拼接出来的语句长这样update [表名] set [列名]ltrim(rtrim([列名]))。单看一条很短但a.name和b.name都是 sysname理论上能到 128 字符表名加列名再算上方括号和空格逼近 500 不是不可能。一旦超长exec(s)拿到的就是半截 SQL抛的是语法错误。要命的是游标里没有IF ERROR 0之类的判断fetch 继续走错误只留在消息窗口一闪而过。大批量表跑下来你看到的是执行完成实际丢了几张表。把变量声明成nvarchar(max)是成本最低的修法顺手在 exec 前后加个错误检查。1.3 方括号硬拼列名遇到特殊列名直接拼坏[b.name]这种写法在列名干净时没事但 SQL Server 允许列名里出现]也允许中文、空格、保留字。用 QUOTENAME() 包一下它会把]自动转义成]]比手写方括号可靠得多。原文那套拼法在这类列上会生成语法错误的语句同样被静默跳过。2. 把脚本和报错贴给 Codex 之前通道得先通SQL 的活最终还是落在本地 SSMS 上但帮我核对这段游标漏了哪几类这种活交给 Codex 效率高得多。前提是它得能正常回话。官方通道额度用完、或者多个 Key 来回切换的时候把 Base URL 统一指到兼容通道省掉来回改配置的时间。2.1 在 TaoToken 创建 Key 并确认模型 ID先打开 TaoToken 注册进控制台创建一个 API Key本文里统一记作YOUR_API_KEY。同一页面上顺手看一眼模型广场把要用的模型 ID 复制下来——不同模型对长脚本的理解能力差别不小核对游标这种活建议挑上下文长一点的。模型 ID 以 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 里模型广场当时的列表为准别用记忆里的名字去猜填错了 Codex 那头只会回一个找不到模型的错误。2.2 Codex 的 config.toml 里 base_url 填 https://taotoken.net/apiCodex 走的是~/.codex/config.tomlWindows 上通常落在C:\Users\你的用户名\.codex\config.toml。把 provider 指向兼容通道注意这里填的是接口地址不要加末尾的/v1model YOUR_MODEL_ID model_provider taotoken [model_providers.taotoken] name taotoken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chatenv_key写的是环境变量的名字不是 Key 本身。接着在 shell 里导出export TAOTOKEN_API_KEYYOUR_API_KEYWindows PowerShell 换成$env:TAOTOKEN_API_KEYYOUR_API_KEY。有一点要盯紧base_url只能是https://taotoken.net/api后面别拖/v1也别把落地页那串带参数的地址填进来那是两回事。2.3 发一句测试消息确认 Codex 真的回了保存 config.toml 之后重开一个终端跑一次codex随便问一句select 1 在 SQL Server 里返回什么。能正常出字说明 Key、Base URL、模型 ID 三样都对上了。这一步别省不然后面把几百行的游标贴进去报的是 401 还是模型不存在都分不清白白浪费一轮排查。3. 让 Codex 核对 syscolumns 关联贴什么、怎么问、边界在哪通道通了只是开始提问方式决定了它给的是套话还是能用的诊断 SQL。这一节的三个小节直接决定你要来回几轮。3.1 提问模板游标全文 报错原文 表结构三件套不要只发一句我的游标漏字段了。把下面三样一次给全游标脚本原文就是那段 sysobjects 关联 syscolumns 的拼接逻辑SSMS 里贴出来的报错原文包括错误号和消息目标库的版本2000 还是 2008 以上以及你想覆盖的类型清单版本信息很关键。SQL Server 2000 只有 sysobjects、syscolumns2005 以后多了 sys.tables、sys.columns、sys.types 这套目录视图语法和字段名都不一样。你不说它可能给你一份 2008 的写法拿去 2000 上跑又是一堆报错。3.2 明确告诉它「不要连库」只出诊断 SQL这一点必须写进 prompt让它只负责生成和解释 SQL不要试图连接任何数据库也不要建议装驱动或挂连接器。Codex 是代码助手不是数据库客户端它没有你的连接串也不该有。正确的工作流是Codex 生成诊断 SQL → 你复制到本地 SSMS 执行 → 把结果集或报错再贴回对话。这条链路里所有对数据的读写动作都发生在你的机器上模型只做文本层面的推理。生产库尤其如此别为了省事把连接信息塞进任何对话窗口。3.3 让它重点回答的三个问题把脚本丢过去时直接点名要它回答这三点比开放式提问收敛得多xtype in (167,175)覆盖了哪些类型漏掉了哪些用表格列出来拼接变量s nvarchar(500)在什么情况下会截断给出估算依据列名用[b.name]拼接存在哪些边界问题是否该换 QUOTENAME问题越具体它越不会兜圈子。回答里如果出现你没见过的函数或视图先拿本地 SSMS 验一遍再用别直接信。4. 在本地 SSMS 执行诊断 SQL再按结果重写游标这一节的所有代码都需要你自己在 SSMS 里跑。Codex 可以帮你写、帮你解释、帮你对照新旧语法但执行权在你手上。4.1 用 sys.types 按类型名筛出所有字符列先跑这段看看当前库里到底有哪些字符类型的列。它比硬编码 xtype 数字直观得多SELECT s.name AS schema_name, t.name AS table_name, c.name AS column_name, ty.name AS type_name, c.max_length FROM sys.columns c JOIN sys.tables t ON t.object_id c.object_id JOIN sys.schemas s ON s.schema_id t.schema_id JOIN sys.types ty ON ty.user_type_id c.user_type_id WHERE t.is_ms_shipped 0 AND ty.name IN (Nvarchar, Nnvarchar, Nchar, Nnchar) ORDER BY s.name, t.name, c.column_id;把结果行数和原文脚本能处理的行数对比一下差多少就是被漏掉的部分。如果库里还是 2000把 sys.tables、sys.columns 换回 sysobjects、syscolumns条件写成a.xtypeU AND b.xtype IN (167,175,231,239)效果一样。4.2 先查哪些列真的有前后空格再决定要不要 UPDATE直接对所有字符列无条件 UPDATE 一次大表上代价太高。先生成一组检查语句只捞出真正脏的列SELECT NSELECT s.name N. t.name N. c.name N AS col_name, COUNT(*) AS dirty_rows FROM QUOTENAME(s.name) N. QUOTENAME(t.name) N WHERE QUOTENAME(c.name) N IS NOT NULL AND QUOTENAME(c.name) N LTRIM(RTRIM( QUOTENAME(c.name) N)); FROM sys.columns c JOIN sys.tables t ON t.object_id c.object_id JOIN sys.schemas s ON s.schema_id t.schema_id JOIN sys.types ty ON ty.user_type_id c.user_type_id WHERE t.is_ms_shipped 0 AND ty.name IN (Nvarchar, Nnvarchar, Nchar, Nnchar);把输出复制出来分批执行得到一份哪些列脏、脏多少行的清单。这里有个细节值得跟 Codex 确认NULL不等于任何值col LTRIM(RTRIM(col))对 NULL 行返回的是 UNKNOWN不会计入脏行。如果你的业务里空格也包括全空白字符串判断条件还得再补一层。4.3 重写后的游标QUOTENAME nvarchar(max) 先 PRINT 后 EXEC确认清单之后再改成批处理。下面这版把前面三类漏都堵上了注意最后一步是 PRINT 而不是直接 EXECSET NOCOUNT ON; DECLARE sql nvarchar(max); DECLARE full_name nvarchar(776); DECLARE col_name nvarchar(128); DECLARE col_cur CURSOR LOCAL FAST_FORWARD FOR SELECT QUOTENAME(s.name) N. QUOTENAME(t.name), QUOTENAME(c.name) FROM sys.columns c JOIN sys.tables t ON t.object_id c.object_id JOIN sys.schemas s ON s.schema_id t.schema_id JOIN sys.types ty ON ty.user_type_id c.user_type_id WHERE t.is_ms_shipped 0 AND ty.name IN (Nvarchar, Nnvarchar, Nchar, Nnchar) ORDER BY s.name, t.name, c.column_id; OPEN col_cur; FETCH NEXT FROM col_cur INTO full_name, col_name; WHILE FETCH_STATUS 0 BEGIN SET sql NUPDATE full_name N SET col_name N LTRIM(RTRIM( col_name N)) N WHERE col_name N IS NOT NULL N AND col_name N LTRIM(RTRIM( col_name N));; PRINT sql; -- 对照无误后再换成 EXEC sp_executesql sql; FETCH NEXT FROM col_cur INTO full_name, col_name; END CLOSE col_cur; DEALLOCATE col_cur;和原文的差别集中在四处类型条件补全了 231、239变量从 nvarchar(500) 提到 nvarchar(max)列名走 QUOTENAME 而不是手拼方括号执行前先 PRINT 一遍人眼过完再放开。跑之前建议先在测试库验证尤其是带触发器的表。5. 跑完一轮回控制台对一下这次对话的消耗游标在测试库跑通、脏行数归零之后回 TaoToken 控制台 看一眼这次核对游标用掉多少额度顺便确认调用记录里没有出现意料之外的失败。如果打算长期用 Codex 处理这类脚本对照的活可以先在 模型对话 里试试不同模型对同一段游标的理解差异再决定主力用哪个。经常要改脚本的可以看看 Coding Plan 的额度够不够覆盖你的日常量Key 需要新的话在 控制台 API Keys 再建一把就行config.toml 里的env_key指向的环境变量换一下即可Base URL 不用动还是https://taotoken.net/api。最后留一句提醒这类批量 UPDATE 脚本真正危险的不是漏字段是 WHERE 写错之后把整列值刷没了。哪怕 Codex 帮你逐行核对过第一次也请在测试库跑把 PRINT 出来的语句扫一遍再放开 EXEC。模型给的是参考执行权始终在你自己手里。