【问题标题】:MySql Cursor - Creating a procedureMySql 游标 - 创建一个过程
【发布时间】:2011-01-06 13:05:50
【问题描述】:

我第一次尝试创建光标。我查看了文档,我理解了这个概念,但我似乎无法让它被声明......

我正在使用:

  • MySql 5.1.41
  • SqlYog 担任经理
  • (在 xampp 安装上本地运行)

即使复制粘贴http://dev.mysql.com/doc/refman/5.1/en/cursors.html 中的示例

    CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT 0;
  DECLARE a CHAR(16);
  DECLARE b,c INT;
  DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
  DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

  OPEN cur1;
  OPEN cur2;

  read_loop: LOOP
    FETCH cur1 INTO a, b;
    FETCH cur2 INTO c;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF b < c THEN
      INSERT INTO test.t3 VALUES (a,b);
    ELSE
      INSERT INTO test.t3 VALUES (a,c);
    END IF;
  END LOOP;

  CLOSE cur1;
  CLOSE cur2;
END;

我马上得到错误: 错误代码:1064

您的 SQL 语法有错误; 检查对应的手册 您的 MySQL 服务器版本 在第 3 行的 '' 附近使用正确的语法

还有很多其他人跟随,

这对我来说没有任何意义,请任何好心人帮助我吗?

谢谢

所以我让示例查询工作(感谢 ajreal),并重置了 DELIMITER。但是当我运行我的查询时:

DELIMITER##
CREATE PROCEDURE RetiraPoints()
BEGIN
    DECLARE userid BIGINT;  
    DECLARE done INT DEFAULT 0;
    DECLARE cur CURSOR FOR SELECT uid FROM viewpoints;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
    OPEN cur;
    read_loop: LOOP 
    FETCH cur INTO userid;
        IF done THEN
            LEAVE read_loop;
        END IF;
        INSERT INTO points (iduser, points, pointcat) VALUES (uid, -1, 1), (userid, -1, 2), (userid, -1, 3), (userid, -1, 4), (userid, -1, 5), (userid, -1, 6);
    END LOOP;
    CLOSE cur;
END;##

我得到: 错误代码:1064

您的 SQL 语法有错误; 检查对应的手册 您的 MySQL 服务器版本 在 'DECLARE done 附近使用正确的语法 INT 默认值 0;声明当前光标为 从视点中选择 uid; ' 在行 1

天哪,这太难了……

【问题讨论】:

  • 我在创建它们时一直收到该错误。太愚蠢了,原来我没有创建程序的权限。除非您以 root 身份登录,否则您需要指定创建之前创建的每个过程的名称并授予对它的访问权限。好傻
  • 是的,但我是以 root 身份登录的,这是我的个人安装
  • 需要在分隔符后面放一个空格,而结尾END不需要;

标签: mysql mysql-error-1064 database-cursor


【解决方案1】:

您忘记将分隔符重置为NOT ;

delimiter ##
...
end##

需要在分隔符后加一个空格

而结尾END不需要;

【讨论】:

  • 谢谢,它适用于示例查询。不知何故,我认为我正在以同样的方式做所有事情,但我无法让我的查询工作。我将编辑我的主要帖子,如果可以请查看
【解决方案2】:

我需要做同样的事情,所以我最终编写了一个存储过程来完成这项工作。我已将它包含在这里,它在 MySQL Workbench 上运行良好。有趣的是,它不会在 Navicat 上正确运行,因为原始 select 语句不会省略 NULL 值,因此会删除所有索引。

我建议您通读代码并分解一些内容并单独运行它们,以确保它会执行您想要的操作。

按照这种编写方式,它应该删除给定连接中所有数据库中的每个外键。除非您想这样做,否则不要按原样运行它。

使用风险自负。

DELIMITER $$

CREATE PROCEDURE `pRemoveAllForeignKeys`()
BEGIN

DECLARE sName TEXT;
DECLARE cName TEXT;
DECLARE tName TEXT;
DECLARE done INT DEFAULT 0;
DECLARE cur CURSOR FOR 
    SELECT TABLE_SCHEMA, CONSTRAINT_NAME, TABLE_NAME
        FROM information_schema.key_column_usage
        WHERE REFERENCED_TABLE_SCHEMA IS NOT NULL
--          AND TABLE_SCHEMA = 'NameOfAParticularSchema' -- use this line to limit the results to one schema
--          LIMIT 1 -- use this the first time because it might make you nervous to run it all at once.
        ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

OPEN cur;
read_loop: LOOP 
FETCH cur INTO sName, cName, tName;
    IF done THEN
        LEAVE read_loop;
    END IF;
    SET @s = CONCAT('ALTER TABLE ',sName, '.', tName, ' DROP FOREIGN KEY ', cName);
--      SELECT @s; -- uncomment this if you want to see the command being sent
    PREPARE stmt FROM @s;
    EXECUTE stmt;
END LOOP;
CLOSE cur;
deallocate prepare stmt;
END

【讨论】:

  • 非常感谢,但我什至不再使用 mySql 了 :)
【解决方案3】:
create or replace procedure cursor_sample()
BEGIN

DECLARE done int default 0 ;
DECLARE data1 varchar(20) ;
DECLARE data2 int ;

DECLARE cur1 CURSOR FOR 
select sname,examscore from student ;
DECLARE CONTINUE HANDLER 
FOR NOT FOUND SET done = 1 ;
OPEN cur1;
loop1:LOOP 
    FETCH cur1 into data1,data2 ;
    insert into student_log(user_name,score) values (data1,data2) ;
    if done = 1 THEN
        LEAVE loop1 ;
    END IF ;
END LOOP;
CLOSE cur1;
END ;
//

--这是存储过程中正确游标实现的示例。---

【讨论】:

    猜你喜欢
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-22
    • 1970-01-01
    相关资源
    最近更新 更多