我通过发送以下查询(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 ;
这会产生以下错误:
错误1064(42000):您的SQL语法有错误;查看与您的MySQL服务器版本对应的手册 在'LIMIT 1 OFFSET ac'附近使用的语法;内环:WHILE(kc&lt; keywordcount)DO to word,word_id from'at line 15
知道为什么会这样吗?
(写这篇文章以创建文章和关键词之间的关系表,在文章视图中启用智能链接。)
答案 0 :(得分:0)
尝试删除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;
答案 1 :(得分:0)
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;
只是一个想法。
答案 2 :(得分:0)
一个问题可能是SET acticleid =(SELECT ...)。试试SELECT .. INTO
:
SELECT id INTO @articleid FROM articles LIMIT 1 OFFSET ac;
存储过程中的变量LIMIT
仅在新的MySQL版本中受支持。请注意,由于您没有ORDER BY
,因此您将获得一个随机行。您似乎想要使用CURSOR
。请参阅docs。
答案 3 :(得分:0)
冒着看似过于严重的风险,我相信您应该重写此过程以使用游标来遍历您的数据库,而不是使用LIMIT进行单独选择。
答案 4 :(得分: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 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 ;
现在我得到了另一个我无法解释的错误:
错误1064(42000):您的SQL语法有错误;检查手册 对应于您的MySQL服务器版本,以便使用正确的语法 靠近'; DECLARE CONTINUE HANDLER for NOT FOUND SET done = TRUE; OPEN关键词; W'在第6行
这个错误让我感到困惑,因为它对处理程序没有问题。处理程序声明为mysql-documentation的example。可能问题是我不能像这样创建两个游标吗?