尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

SQL SERVER 游标+事务实例:用 TaoToken 统一 Key 跑通配置骨架

SQL SERVER 游标+事务实例:用 TaoToken 统一 Key 跑通配置骨架 1. 从一段真实脚本说起游标里的事务到底怎么收尾SQL SERVER 游标加事务是很多做数据迁移、批量对账、单据状态刷新的同学绕不开的一关。它要解决的问题很具体逐行拿到一批单号对每一行做处理最后要么全部成功提交要么整体回滚不能出现改了一半的脏数据。适合谁适合正在写存储过程、批处理脚本或者被FETCH_STATUS、ERROR、commit tran、rollback tran绕晕的开发者。我见过一段很典型的脚本结构是这样的先declare autosale_cursor cursor for select distinct cVoucher_No from ...然后openfetch next进循环循环里累加ERROR循环结束后判断错误计数为 0 就commit tran否则rollback tran最后close加deallocate。骨架没问题但真跑起来经常遇到两个坑一是ERROR在每次语句后都会被重置累加时机不对就永远抓不到错二是游标没关、事务没配对连接池里残留锁。这篇就围绕这个经典实例把配置骨架和验证动作补齐。同时我会用 TaoToken 的统一 Key 通道把模型对话、接入文档这些调试入口串起来方便你在写 SQL 的同时快速查参数、对报错。TaoToken 在这里的角色是统一 API 通道官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 不改变你本地 SQL SERVER 的任何行为只是让配置和调试更顺手。2. 前置准备TaoToken 统一 Key 与本地环境2.1 为什么要在 SQL 场景里引入统一 Key写游标事务脚本时最烦的不是语法而是调试过程中要反复查文档、问模型、对参数。如果每个工具都要单独配一套 Key切换成本很高。TaoToken 的思路是给你一个统一 Key模型对话、接入文档、Coding Plan 都走同一个通道。对 SQL 开发者来说实际收益是写config.toml和settings.json时鉴权字段只维护一份脚本里读环境变量就行。需要先拿到 Key。进入控制台创建https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 然后在 API Keys 页面生成https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。生成后复制保存后面配置文件里用占位符YOUR_TAOTOKEN_KEY代替不要直接写死在脚本里。2.2 本地 SQL SERVER 侧要确认的三件事第一确认你有可用的测试库别在生产库上练游标事务。第二确认登录账号有BEGIN TRAN、COMMIT、ROLLBACK权限。第三确认cf20190219这类表名在你库里真实存在否则脚本一open就报对象名无效。注意游标默认是READ_ONLY还是可更新取决于FOR后面的子句。只读遍历建议显式写FOR READ ONLY减少锁竞争。2.3 配置骨架的定位下面给的config.toml和settings.json是骨架不是完整业务配置。它们的作用是让你把 TaoToken 的 Key、API 地址、模型名集中管理SQL 脚本通过环境变量或外部程序读取。这样你调游标逻辑时鉴权部分不用动。3. 可复制配置config.toml 与 settings.json 骨架3.1 config.toml 骨架# config.toml # TaoToken 统一 Key 配置骨架 [taotoken] api_base https://taotoken.net/api api_key YOUR_TAOTOKEN_KEY timeout_seconds 60 [taotoken.model] # 调试 SQL 报错、生成游标模板时用的模型 chat_model claude-sonnet # 长上下文场景比如贴整段存储过程 coding_model claude-sonnet [sqlserver] host 127.0.0.1 port 1433 database hbposev9_branch user sa password YOUR_DB_PASSWORD driver ODBC Driver 18 for SQL Server [cursor] fetch_batch 1 error_accumulate true这里api_base用不带 UTM 的地址api_key走占位符。[cursor]段是我自己加的用来标记游标行为实际读取时你可以忽略也可以映射到脚本参数。3.2 settings.json 骨架{ taotoken: { api_base: https://taotoken.net/api, api_key_env: TAOTOKEN_API_KEY, default_model: claude-sonnet, endpoints: { chat: https://taotoken.net/api, coding_plan: https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content, doc: https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content } }, sqlserver: { connection_string: DRIVER{ODBC Driver 18 for SQL Server};SERVER127.0.0.1,1433;DATABASEhbposev9_branch;UIDsa;PWDYOUR_DB_PASSWORD;TrustServerCertificateyes }, cursor_task: { table: cf20190219, column: cVoucher_No, commit_on_success: true, rollback_on_error: true } }api_key_env指向环境变量比明文写 Key 安全。endpoints里放了文档和 Coding Plan 的 deep link方便你在 IDE 里直接跳转。3.3 环境变量注入Linux 或 macOSexport TAOTOKEN_API_KEY你的Key export SQLSERVER_PASSWORD你的库密码Windows PowerShell$env:TAOTOKEN_API_KEY 你的Key $env:SQLSERVER_PASSWORD 你的库密码这样配置文件里只留占位符提交到仓库也不会泄露。4. 游标事务实例从声明到提交回滚的完整动作4.1 修正后的脚本骨架原始脚本最大的问题是ERROR累加位置。ERROR只反映上一条语句循环里如果先print再累加print会把错误状态冲掉。正确做法是每条可能出错的语句后立刻判断。下面是我调整后的版本USE hbposev9_branch; GO SET NOCOUNT ON; DECLARE voucherno VARCHAR(60); DECLARE i INT 1; DECLARE error INT 0; DECLARE autosale_cursor CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT cVoucher_No FROM cf20190219; OPEN autosale_cursor; BEGIN TRAN; FETCH NEXT FROM autosale_cursor INTO voucherno; WHILE FETCH_STATUS 0 BEGIN BEGIN TRY -- 这里放你的业务处理比如更新单据状态 PRINT voucherno; PRINT i; SET i i 1; END TRY BEGIN CATCH SET error error 1; PRINT ERROR at voucher: ISNULL(voucherno, NULL); PRINT ERROR_MESSAGE(); END CATCH FETCH NEXT FROM autosale_cursor INTO voucherno; END IF error 0 BEGIN COMMIT TRAN; PRINT COMMIT OK, total rows: CAST(i - 1 AS VARCHAR(10)); END ELSE BEGIN ROLLBACK TRAN; PRINT ROLLBACK, error count: CAST(error AS VARCHAR(10)); END CLOSE autosale_cursor; DEALLOCATE autosale_cursor; GO关键改动用TRY...CATCH替代裸ERROR累加LOCAL FAST_FORWARD减少游标开销SET NOCOUNT ON避免行数消息干扰。4.2 提交路径验证先造两条正常数据确保cf20190219里有cVoucher_No。执行脚本预期输出V001 1 V002 2 COMMIT OK, total rows: 2看到COMMIT OK说明事务正常提交游标遍历完整。4.3 回滚路径验证故意制造错误比如在TRY块里加一句SELECT 1/0;。再执行预期输出ERROR at voucher: V001 Divide by zero error encountered. ROLLBACK, error count: 1看到ROLLBACK说明错误被捕获事务整体回滚。这一步是很多人漏掉的只测提交不测回滚上线后遇到脏数据才发现问题。4.4 用 TaoToken 辅助排查如果报错信息看不懂可以把ERROR_MESSAGE()的输出贴到模型对话里问https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入细节查文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。长期写批处理脚本的话Coding Plan 更合适https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。5. 本篇常见错排查5.1 游标未关闭导致锁残留现象脚本跑完表还被锁着其他会话查不动。原因CLOSE或DEALLOCATE没执行或者中途RETURN跳过了。排查查sys.dm_exec_cursors看有没有残留游标。修复把CLOSE和DEALLOCATE放在TRY...CATCH的FINALLY逻辑里或者用LOCAL游标让作用域自动回收。5.2 事务计数不匹配现象报Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements。原因嵌套事务里COMMIT次数和BEGIN TRAN对不上或者ROLLBACK后没重置。排查用TRANCOUNT打印当前层级。修复确保每个BEGIN TRAN都有配对的COMMIT或ROLLBACK嵌套时用SAVE TRAN做保存点。5.3 ERROR 抓不到错现象明明有错error还是 0。原因ERROR被后续语句重置或者错误发生在TRY块外。排查在每条语句后立刻SELECT ERROR。修复改用TRY...CATCHCATCH里用ERROR_NUMBER()、ERROR_MESSAGE()获取详情。5.4 配置读取失败现象脚本读不到TAOTOKEN_API_KEY报鉴权失败。原因环境变量没导出或者config.toml里写的是明文占位符没替换。排查echo $TAOTOKEN_API_KEY确认。修复重新导出环境变量或者把 Key 写进本地不提交的.env文件。5.5 游标性能差现象几万行数据跑几分钟。原因默认游标是动态的每行都重新查。排查看执行计划有没有反复扫描。修复用FAST_FORWARD或STATIC只读场景优先FAST_FORWARD。6. 把配置和验证固定成习惯游标事务这类脚本写完不算完提交和回滚两条路径都要跑一遍。我自己的习惯是先在测试库造 3 条数据跑提交路径再故意改坏一条跑回滚路径最后查TRANCOUNT确认归零。配置侧config.toml和settings.json只留占位符Key 走环境变量TaoToken 的 API 地址固定用 https://taotoken.net/api 调试入口按需走模型对话或文档。如果你要把这套骨架接到更长的批处理流程里Coding Plan 的通道可以省掉反复配 Key 的麻烦https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。Key 管理在控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 生成入口在 API Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。把CLOSE、DEALLOCATE、TRANCOUNT检查写进你的脚本模板下次就不用重新踩一遍。
返回列表