2012-02-11 220 views
0


我得到通过发送下面的查询(MYSQL 5.0)的错误:MySQL的程序语法错误

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): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LIMIT 1 OFFSET ac); innerloop: WHILE (kc < keywordcount) DO TO word, word_id from' at line 15

任何想法,为什么出现这种情况?

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

+0

1.错误报告中的单词DO和单词片段TO是你问题的一部分的奇怪跳过? – 2012-02-11 14:55:40

+0

2.是否可能需要SELECT INTO用户定义的变量而不是声明的过程变量? – 2012-02-11 14:58:25

+0

你是什么意思的“用户定义”变量? – enigma 2012-02-11 15:43:21

回答

0

尽量去除,而标签:

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; 
+0

我试过了,但是错误保持不变。 – enigma 2012-02-11 15:49:22

0

MySQL有连接特定用户定义的变量形式为@varname,并声明您在代码示例中使用的类型的过程变量。根据我对程序的经验,有时只允许其中一种类型,如果我正确记得,那么SELECTing 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; 

只是一个想法。

+0

好的,谢谢我会改变它,看看它是否有效。 – enigma 2012-02-14 09:16:55

0

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

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

可变LIMIT在存储过程中仅在新的MySQL版本的支持。请注意,由于您没有ORDER BY,您将得到一个随机行。它看起来像你想用CURSOR来代替。请参阅docs

+0

感谢您的提示。我会稍后再尝试。 – enigma 2012-02-14 09:16:21

0

在看似过分危险的情况下,我相信你应该重写这个过程来使用游标遍历数据库,而不是使用LIMIT进行单独选择。

看到Cursors in MySQL Docs

+0

感谢您的提示。我会稍后再尝试。 – enigma 2012-02-14 09:15:13

0

感谢您的帮助迄今。 Tom Haws的想法被证明是正确的。 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 [email protected] 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): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN articlecursor; W' at line 6

这个错误让我困惑因为它不会对处理程序有问题。该处理程序在mysql文档的example中声明。问题可能是我不能创建两个这样的游标?