【问题标题】:mysql procedure syntax errormysql过程语法错误
【发布时间】:2012-02-11 13:35:28
【问题描述】:


我通过发送以下查询 (MYSQL 5.0) 得到一个错误:

    DELIMITER //
    CREATE PROCEDURE relationTable ()
    BEGIN
        DECLARE articlecount int;
        DECLARE keywordcount int;
        DECLARE articlehits int;
        DECLARE ac int DEFAULT 0;
        DECLARE kc int;
        DECLARE articleid int;
        DECLARE word varchar(100);
        DECLARE word_id int;
        SET articlehits = 0;
        SET articlecount = (SELECT count(id) from articles);
        SET keywordcount = (SELECT count(id) from keywords);
        outerloop: WHILE (ac < articlecount) DO
            SET kc = 0;
            SET articleid = (SELECT id from articles LIMIT 1 OFFSET ac);
            innerloop: WHILE (kc < keywordcount) DO
                IF (articlehits < 5) THEN
                    SELECT keyword, id INTO word, word_id from keywords LIMIT 1 OFFSET kc;
                    IF (0 < (SELECT COUNT(id) from articles WHERE id=articleid AND CONCAT(title, " ",text) REGEXP word)) THEN
                        INSERT INTO articles (id, articleID, keywordID, type) VALUES(NULL, articleid, word_id, 'type1');
                        SET articlehits = articlehits + 1;
                    END IF;
                    SET kc = kc + 1;
                ELSE
                    SET kc = keywordcount;
                END IF;
            END WHILE innerloop;
            SET ac = ac + 1;
        END WHILE outerloop;
    END;
    //
    DELIMITER ;

这会产生以下错误:

ERROR 1064 (42000):您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册以获取正确的 在 'LIMIT 1 OFFSET ac) 附近使用的语法;内环:WHILE(kc

知道为什么会这样吗?

(写这个来创建文章和关键字之间的关系表,以在文章视图中启用智能链接。)

【问题讨论】:

  • 1.错误报告中奇怪的跳过是否来自单词 DO 和单词片段 TO 您问题的一部分?
  • 2.您是否可能需要 SELECT INTO 用户定义的变量而不是声明的过程变量?
  • “用户定义”变量是什么意思?
  • 是的,我也想知道这个错误输出的碎片
  • MySQL 具有@varname 形式的特定于连接的用户定义变量和您正在使用的类型的声明过程变量。根据我的程序经验,有时只允许其中一种类型,如果我没记错的话,其中一种情况可能是在选择 INTO 时。如果您想将其标记为正确,我会将其作为答案。

标签: mysql syntax-error procedure


【解决方案1】:

尝试删除while标签:

WHILE (ac < articlecount) DO
            SET kc = 0;
            SET articleid = (SELECT id from articles LIMIT 1 OFFSET ac);
            WHILE (kc < keywordcount) DO
                IF (articlehits < 5) THEN
                    SELECT keyword, id INTO word, word_id from keywords LIMIT 1 OFFSET kc;
                    IF (0 < (SELECT COUNT(id) from articles WHERE id=articleid AND CONCAT(title, " ",text) REGEXP word)) THEN
                        INSERT INTO articles (id, articleID, keywordID, type) VALUES(NULL, articleid, word_id, 'type1');
                        SET articlehits = articlehits + 1;
                    END IF;
                    SET kc = kc + 1;
                ELSE
                    SET kc = keywordcount;
                END IF;
            END WHILE;
            SET ac = ac + 1;
        END WHILE;

【讨论】:

    【解决方案2】:

    MySQL 具有@varname 形式的特定于连接的用户定义变量和您在代码示例中使用的类型的声明过程变量。根据我的程序经验,有时只允许其中一种类型,如果我没记错的话,其中一种情况可能是在选择 INTO 时。您可以在这里尝试使用用户定义的变量,如下所示:

        SET articleid = (SELECT id from articles LIMIT 1 OFFSET ac);
        innerloop: WHILE (kc < keywordcount) DO
            IF (articlehits < 5) THEN
                SELECT keyword, id INTO @word, @word_id from keywords LIMIT 1 OFFSET kc;
    

    只是一个想法。

    【讨论】:

      【解决方案3】:

      一个问题可能是 SET acticleid = (SELECT...)。试试SELECT .. INTO:

      SELECT id INTO @articleid FROM articles LIMIT 1 OFFSET ac;
      

      存储过程中的变量LIMIT 仅在新的 MySQL 版本中受支持。请注意,由于您没有ORDER BY,您将得到一个随机行。看起来您想改用CURSOR。见docs

      【讨论】:

      • 感谢您的提示。我稍后再试。
      【解决方案4】:

      冒着显得过于关键的风险,我认为您应该重写此过程以使用游标来遍历您的数据库,而不是使用 LIMIT 进行单个选择。

      Cursors in MySQL Docs

      【讨论】:

      • 感谢您的提示。我稍后再试。
      【解决方案5】:

      感谢您迄今为止的帮助。 事实证明,汤姆霍斯的想法是正确的。 SELECT INTO 语句的变量必须是用户定义的。 我编辑了我的代码以使用光标和用户定义的变量,如下所示:

      delimiter //
      CREATE PROCEDURE relationTable ()
      BEGIN
          DECLARE articlehits int;
          DECLARE looparticles int DEFAULT TRUE;
          DECLARE loopwords int DEFAULT TRUE;
          DECLARE done INT DEFAULT FALSE;     
          DECLARE keywordcursor CURSOR FOR SELECT keyword, id FROM keywords;
          DECLARE articlecursor CURSOR FOR SELECT id FROM articles;
          DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 
          OPEN articlecursor;
          WHILE (looparticles) DO
              FETCH articlecursor INTO @articleid;
              IF done THEN SET looparticles = FALSE;
              ELSE
                  SET articlehits = 0;
                  OPEN keywordcursor;
                  WHILE (loopwords) DO
                      FETCH keywordcursor INTO @word, @wordid;
                      IF (articlehits < 5) AND NOT done THEN
                          IF (0 < (SELECT COUNT(id) FROM articles WHERE id=@articleid AND CONCAT(title, " ", text) REGEXP @word)) THEN
                              INSERT INTO keyword_article_rel (id, meldungID, wordID) VALUES(NULL, @articleid, @wordid);
                              SET articlehits = articlehits + 1;
                          END IF;
                      ELSE
                          SET loopwords = FALSE;
                          CLOSE keywordcursor;
                          SET done = FALSE;
                      END IF;
                  END WHILE;
              END IF;
          END WHILE;
          CLOSE articlecursor;
          END;
          //
          delimiter ;
      

      现在我遇到了另一个我真的无法解释的错误:

      ERROR 1064 (42000):您的 SQL 语法有错误;检查手册 对应于您的 MySQL 服务器版本,以便使用正确的语法 靠近 '; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 打开文章光标; W' 在第 6 行

      这个错误让我很困惑,因为处理程序没有问题。处理程序在 mysql 文档的 example 中声明。问题是我不能像这样创建 两个 游标吗?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-12
        • 2014-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多