ARTICLE DETAIL

资讯详情

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

MySQL 游标例子:用 TaoToken 统一 Key 跑通存储过程逐行处理配置

MySQL 游标例子:用 TaoToken 统一 Key 跑通存储过程逐行处理配置 1. 为什么要在存储过程里用游标逐行处理MySQL 游标Cursor是存储过程里用来遍历结果集、逐行加工数据的机制。它解决的是「一条 UPDATE 搞不定、必须按行判断再决定怎么改」的场景比如按员工薪资分档写日志、按订单状态逐条补字段、按批次把明细汇总进报表表。适合谁后端开发者、数据加工同学、需要把批量逻辑下沉到数据库侧减少应用层往返的人。我先把结论放前面游标本身不难难的是「声明顺序」和「循环退出条件」这两处十个人写游标八个栽在这。这篇会给你一份可直接复制的存储过程骨架覆盖 DECLARE / CURSOR / FETCH / CLOSE 全流程再配上用 TaoToken 统一 Key 管理模型通道的 settings.json 配置片段让你在写 SQL 的同时把 AI 辅助生成/审查存储过程这条链路也一次跑通。核心检索词先对齐MySQL 游标是什么——它是存储过程内声明的结果集遍历器能做什么——逐行 FETCH 到变量后做任意加工适合谁——需要在数据库侧做批量数据加工的后端开发者。下面从建表、写过程、调用、验证一步步来。2. TaoToken 前置统一 Key 与 settings.json 配置写游标时经常需要 AI 帮你检查语法、生成测试数据、解释报错。如果每个工具都单独配一套 Key切换起来很烦。TaoToken 的思路是给你一个统一 Key通过同一个 API 通道对接不同模型配置一次到处用。官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 这个不加 UTM。你需要先去控制台拿 Key地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite Key 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。拿到之后很多支持 OpenAI 兼容协议的工具都能直接读 settings.json。下面是一份可复制的配置片段把 base_url 指向 TaoToken 的 API 通道{ provider: openai-compatible, base_url: https://taotoken.net/api, api_key: sk-你的TaoToken统一Key, model: claude-sonnet-4-5, timeout: 60, max_tokens: 4096 }注意base_url 只写到 /api 这一层具体路径由客户端按 OpenAI 兼容规范拼接不要自己加 /v1 之外的尾巴否则容易 404。如果你用的是 Claude Code 这类编码工具配置方式略有不同可以参考 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里的接入说明。想先验证模型通不通直接去模型对话页 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 发一句话测试即可。长期做编码和 Agent 任务的话Coding Plan 更划算入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。配置好之后你就可以让模型帮你审查下面的游标存储过程或者根据你的表结构生成变体。Key 统一了切换模型不用改代码这点在反复调试 SQL 时很省事。3. 可复制配置游标存储过程完整骨架先建一张示例表模拟员工薪资数据。字段简单方便你对照 FETCH 的变量顺序CREATE TABLE employees ( employee_id INT PRIMARY KEY, first_name VARCHAR(50), last_name VARCHAR(50), salary DECIMAL(10, 2) ); INSERT INTO employees (employee_id, first_name, last_name, salary) VALUES (1, John, Doe, 50000), (2, Jane, Smith, 60000), (3, Mike, Johnson, 55000);再建一张结果表用来承接逐行加工后的输出这样验证时能直接查表确认每行都对CREATE TABLE salary_audit ( employee_id INT, full_name VARCHAR(101), salary DECIMAL(10, 2), grade VARCHAR(10), processed_at DATETIME );下面是完整的游标存储过程。注意声明顺序变量 → 游标 → HANDLER这个顺序不能乱否则 MySQL 会报 1337 或 1327 之类的错。DELIMITER $$ CREATE PROCEDURE process_employees() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE emp_id INT; DECLARE emp_first_name VARCHAR(50); DECLARE emp_last_name VARCHAR(50); DECLARE emp_salary DECIMAL(10, 2); DECLARE emp_grade VARCHAR(10); -- 声明游标结果集列顺序必须和 FETCH 变量顺序一致 DECLARE employee_cursor CURSOR FOR SELECT employee_id, first_name, last_name, salary FROM employees ORDER BY employee_id; -- 声明 HANDLER结果集取完后把 done 置为 TRUE DECLARE CONTINUE HANDLER FOR NOT FOUND SET done TRUE; OPEN employee_cursor; read_loop: LOOP FETCH employee_cursor INTO emp_id, emp_first_name, emp_last_name, emp_salary; IF done THEN LEAVE read_loop; END IF; -- 逐行加工按薪资分档 IF emp_salary 60000 THEN SET emp_grade HIGH; ELSEIF emp_salary 50000 THEN SET emp_grade MID; ELSE SET emp_grade LOW; END IF; INSERT INTO salary_audit (employee_id, full_name, salary, grade, processed_at) VALUES (emp_id, CONCAT(emp_first_name, , emp_last_name), emp_salary, emp_grade, NOW()); END LOOP; CLOSE employee_cursor; END$$ DELIMITER ;几个关键点拆开说。第一DECLARE CONTINUE HANDLER FOR NOT FOUND必须放在游标声明之后因为 HANDLER 要捕获的是 FETCH 触发的 NOT FOUND 条件。第二FETCH 的变量列表顺序要和 SELECT 的列顺序严格对应错位了不会报错但数据会串。第三IF done THEN LEAVE read_loop要放在 FETCH 之后、处理逻辑之前否则最后一行会被漏掉或多处理一次。调用存储过程CALL process_employees();4. 验证请求与成功结果调用完之后直接查结果表确认每行都处理正确SELECT * FROM salary_audit ORDER BY employee_id;预期输出应该是三行John 50000 对应 MIDJane 60000 对应 HIGHMike 55000 对应 MIDprocessed_at 是执行时刻。如果行数不对先看是不是 HANDLER 没生效导致死循环或者 done 判断位置错了。再验证一次幂等性重复 CALL 两次结果表会追加说明游标每次都是全量遍历。如果你要的是「只处理未加工的行」得在游标 SELECT 里加 WHERE 条件过滤比如WHERE employee_id NOT IN (SELECT employee_id FROM salary_audit)。想确认游标循环次数可以在过程里加一个计数器变量循环结束时 SELECT 出来DECLARE row_count INT DEFAULT 0; -- 在 LOOP 内处理逻辑后 SET row_count row_count 1; -- 在 CLOSE 之后 SELECT row_count AS total_processed;这样你能直观看到游标到底遍历了几行和源表 COUNT 对得上就说明没漏没重。5. 本篇常见错排查报错 1337Cursor declaration after handler。原因就是 HANDLER 写在了 CURSOR 前面。MySQL 要求变量 → 游标 → HANDLER 这个顺序调换一下即可。报错 1327Undeclared variable。FETCH INTO 里的变量名拼错或者变量声明在游标之后。所有 FETCH 用到的变量必须在游标声明之前就 DECLARE 好。循环只处理了第一行就退出。多半是 HANDLER 的 NOT FOUND 被别的地方提前触发了比如循环里又写了一个 SELECT ... INTO它取不到数据也会触发 NOT FOUND把 done 置 TRUE。解决办法是给内层查询单独加 HANDLER或者避免在游标循环里用裸 SELECT INTO。最后一行没被处理。检查IF done THEN LEAVE的位置。如果放在 FETCH 之前第一行还没取就退出了如果 FETCH 后没立即判断最后一行取完后 done 已经是 TRUE但你的处理逻辑可能又跑了一遍空数据。游标结果集太大导致内存吃紧。游标会在服务器侧保持结果集几万行还行上百万行就要考虑分批。可以在游标 SELECT 里加 LIMIT 配合外层循环或者干脆改用批量 UPDATE 语句游标只留给真正需要逐行判断的场景。DELIMITER 忘了改回来。建完存储过程后如果没把DELIMITER ;还原后续普通 SQL 会一直等结束符表现为「敲了分号没反应」。养成习惯过程定义完立刻还原。6. 把 AI 辅助接进你的游标调试流程游标调试最烦的是报错信息不直观1337、1327 这种编号得查文档。这时候把报错贴给模型让它结合你的存储过程上下文解释比翻手册快。用 TaoToken 统一 Key 的好处是你在编辑器插件、命令行工具、对话页之间切换时不用重新配 Keysettings.json 里改个 model 字段就能换模型对比答案。接入相关的完整说明在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite Key 在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 管理。如果你主要做编码和 Agent 类任务Coding Plan 的额度模型更适合长期跑入口 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。想快速验证某个模型对 SQL 的理解能力直接去 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 发一段游标代码让它找 bug。最后留个实用技巧把上面那份存储过程骨架存成模板每次新场景只改游标 SELECT 和循环内的加工逻辑声明部分原样保留。这样能避开 90% 的声明顺序类报错。跑通之后记得用SHOW PROCEDURE STATUS WHERE Name process_employees确认过程已创建再用SELECT COUNT(*) FROM salary_audit对一下行数两个数对上了游标这条链路就算彻底通了。
返回列表