必须先执行OPEN cursor_name再FETCH或CLOSE,DECLARE仅定义游标不分配资源,未OPEN就FETCH必然报ERROR 1326。

MySQL 存储过程报 ERROR 1326: Cursor is not open 怎么办
直接说结论:这个错误不是游标“打不开”,而是你在没 OPEN 它的情况下就执行了 FETCH 或 CLOSE。MySQL 不会自动帮你打开游标,必须显式调用 OPEN cursor_name,且只能在 OPEN 之后才能 FETCH 和 CLOSE。
为什么刚写完 DECLARE 就 FETCH 会报 1326
常见错误是把游标声明和取值逻辑混在一起,比如:
DECLARE cur CURSOR FOR SELECT id FROM users; FETCH cur INTO @id; -- ❌ 这里立刻报 ERROR 1326
原因很简单:DECLARE 只是定义游标结构,不分配运行时资源;OPEN 才真正执行查询、绑定结果集、分配内存。没 OPEN 就 FETCH,MySQL 直接拒绝——它连“有没有数据”都还不知道。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
-
OPEN必须出现在所有FETCH和CLOSE之前,且只能对已DECLARE的游标执行 - 不能在
IF条件里“按需OPEN”,再在外面FETCH——作用域错乱会导致 1326 - 嵌套块中声明的游标,
OPEN和CLOSE必须在同一块内,跨BEGIN END会报错 - 如果存储过程中有多个游标,别复用同一个名字(比如先
DECLARE cur,又DECLARE cur),MySQL 会报 1337(重复声明)而不是 1326,但排查路径容易混淆
FETCH 前漏掉 OPEN 的典型场景
最容易踩坑的是动态逻辑分支或异常处理后忘记补 OPEN:
- 在
IF condition THEN OPEN cur1; ELSE OPEN cur2; END IF;之后,直接写FETCH cur1 INTO ...—— 如果走的是ELSE分支,cur1根本没开,FETCH 就崩 - 加了
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION,但 handler 里只CLOSE没LEAVE,后续代码继续执行到FETCH,而此时游标可能根本没成功OPEN - 用
REPEAT ... UNTIL done循环时,把OPEN放在循环体里(每次循环都OPEN),但没关,第二次OPEN会报 ERROR 1325(Cursor is already open);而如果把OPEN放在循环外却漏写了,第一次FETCH就 1326
CLOSE 后又 FETCH 也会触发 1326
另一个隐蔽来源:游标已经 CLOSE 了,但后续逻辑(比如日志记录、异常重试)又试图 FETCH。MySQL 关闭后不会自动重开,也不会静默忽略,而是坚定报 1326。
-
CLOSE是单向操作,不可逆;再次使用必须重新OPEN - 别在
LEAVE或EXIT前漏掉CLOSE,否则游标处于“已声明但未打开”状态,下次调用该过程时若复用同名游标,可能因内部状态残留导致行为异常 - 高并发下,多个连接同时调用同一存储过程,每个连接的游标状态完全独立——所以不要假设“上一次成功,这次就一定行”,每次都要走完整
DECLARE → OPEN → FETCH → CLOSE流程
最稳妥的做法,是在每个 FETCH 前加一行注释提醒自己是否已 OPEN,并在 CLOSE 后立刻清空相关变量(如 SET done = FALSE),避免状态污染。游标不是黑盒,它的生命周期全靠你手动掐住起点和终点。

















