Синтаксическая ошибка процедуры mysql - PullRequest
0 голосов
/ 11 февраля 2012


Я получаю сообщение об ошибке, отправив следующий запрос (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 (кц < keywordcount) DO TO word, word_id из 'в строке 15

Есть идеи, почему это происходит?

(Написал это для создания таблицы отношений между статьями и ключевыми словами, чтобы включить умные ссылки в представлении статьи.)

Ответы [ 5 ]

0 голосов
/ 20 февраля 2012

Спасибо за вашу помощь. Идея Тома Хоуса оказалась верной. Переменные для оператора 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 для правильного использования синтаксиса возле '; ЗАЯВИТЕ ПРОДОЛЖАЕТЕ ОБРАЩАТЬСЯ ЗА НЕ НАЙДЕННЫЙ УСТАНОВЛЕНО выполнено = ИСТИНА; ОТКРЫТЫЙ артикль статьи; W 'в строке 6

Эта ошибка меня смущает, потому что у нее не может быть проблем с обработчиком. Обработчик объявляется как в примере документации mysql. Может быть проблема в том, что я не могу создать два курсора, как это?

0 голосов
/ 13 февраля 2012

С риском казаться чрезмерно критическим, я считаю, что вам следует переписать эту процедуру, чтобы использовать курсоры для обхода ваших баз данных, а не отдельные выборки с помощью LIMIT.

см. Курсоры в MySQL Docs

0 голосов
/ 13 февраля 2012

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;

Просто идея.

0 голосов
/ 13 февраля 2012

Одной из проблем может быть SET acticleid = (SELECT ...). Попробуйте с SELECT .. INTO:

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

Переменная LIMIT в хранимых процедурах поддерживается только в новых версиях MySQL. Обратите внимание, что, поскольку у вас нет ORDER BY, вы получите случайную строку. Похоже, вы хотите использовать CURSOR вместо. См. документы .

0 голосов
/ 11 февраля 2012

Попробуйте удалить метки 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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...