Хранимая процедура MySQL, дающая разные результаты в командной строке

У меня есть простая хранимая процедура MySQL, предназначенная для возврата всех дочерних записей для данного узла. Моя проблема в том, что когда я набираю это вручную, он возвращает правильные результаты, но когда я помещаю тот же код в хранимую процедуру, он возвращает только родительский идентификатор.

Я был бы очень признателен за некоторые рекомендации!

Например, когда я вызываю свою процедуру (код ниже), я получаю:

call find_child(1006);
+--------+
| nodeid |
+--------+
|   1006 |
|   1006 |
|   1006 |
|   1006 |
+--------+
4 rows in set (0.01 sec)

НО. Когда я вырезаю и вставляю команду, я получаю правильный набор результатов:

mysql> create temporary table KID_TABLE (nodeid INT);
Query OK, 0 rows affected (0.00 sec)

mysql> insert ignore into KID_TABLE (nodeid) select nodeid from CORPORATENODE 
       where parentid in (1006);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from KID_TABLE;
+--------+
| nodeid |
+--------+
|   1007 |
|   1008 |
|   1031 |
|   1038 |
+--------+
4 rows in set (0.00 sec)

Вот код:

DELIMITER $$

DROP PROCEDURE IF EXISTS `find_child`$$
CREATE PROCEDURE  `find_child`( IN NodeID INT)
    DETERMINISTIC
BEGIN
declare nid INT;
set nid= NodeID;
create temporary table KID_TABLE (nodeid INT);
insert ignore into KID_TABLE (nodeid) select nodeid 
from CORPORATENODE where parentid in (1006);
select * from KID_TABLE;
drop table KID_TABLE;
END $$

DELIMITER ;

Вот DDL для таблицы PARENT

    CREATE TABLE  `PARENT` (  
    `NODEID` int(11) NOT NULL AUTO_INCREMENT,  
    `PARENTID` int(11) NOT NULL DEFAULT '0' COMMENT '0 value means top node',  
    `NAME` varchar(50) NOT NULL,  
    PRIMARY KEY (`NODEID`) USING BTREE  
    ) ENGINE=InnoDB;

person GalwayGirl    schedule 21.11.2011    source источник
comment
Просто быстрый вопрос, вы запускаете это на Windows? Ваш случай выглядит запутанным, и это не будет хорошо работать в системе Linux с настроенным по умолчанию mysql.   -  person Andreas Wederbrand    schedule 21.11.2011
comment
Ваша процедура НЕ ДЕТЕРМИНИСТИЧЕСКАЯ. Попробуйте без этого (неправильного) спецификатора.   -  person pilcrow    schedule 21.11.2011


Ответы (2)


Mysql вернет вашу переменную NodeId в вашем select nodeid from CORPORATENODE where parentid in (1006);

Вместо этого измените переменную на in_NodeID.

DELIMITER $$

DROP PROCEDURE IF EXISTS `find_child`$$
CREATE PROCEDURE  `find_child`( IN in_NodeID INT)
BEGIN
create temporary table KID_TABLE (nodeid INT);
insert ignore into KID_TABLE (nodeid) select nodeid 
from CORPORATENODE where parentid in (in_NodeID);
select * from KID_TABLE;
drop table KID_TABLE;
END $$

DELIMITER ;

Но тогда, конечно, зачем использовать временную таблицу?

DELIMITER $$

DROP PROCEDURE IF EXISTS `find_child`$$
CREATE PROCEDURE  `find_child`( IN in_NodeID INT)
BEGIN
select nodeid from CORPORATENODE where parentid in (in_NodeID);
END $$

DELIMITER ;
person Andreas Wederbrand    schedule 21.11.2011

Спасибо, Андреас и др.,

Я нашел обходной путь сразу после публикации - типичный. Но до сих пор не мог опубликовать свое решение. Я использую Linux, но у меня установлено значение lower_case_table_names=1, поэтому регистр не имеет значения. (Я думаю?)

Андреас, мне понадобилась временная таблица, так как после того, как я выбрал все дочерние записи для узла, мне нужно было обновить все дочерние записи в таблице NODEVERSION. Я запускал это с помощью триггера в таблице NODEVERSION и сталкивался с проблемами, когда обновлял таблицу вызовов и т. д. Вот почему я создал новую CHILD_TABLE.

Итак, я обнаружил, что (даже оставив DETERMINISTIC в... извините pilcrow!) Следующее сработало, как и ожидалось - все, что я сделал, это добавило псевдонимы... (Приведенный ниже код немного отличается от приведенного выше, поскольку я упростил приведенный выше код для своего вопроса. )

Не совсем понимаю, почему псевдонимы исправили первоначальную проблему, но это сработало. Возможно, вы, знатоки, знаете, почему?

    CREATE PROCEDURE `find_child`( IN NodeID int)
    DETERMINISTIC
    BEGIN
     declare nid INT;
     declare rows_before INT DEFAULT 0;
     declare rows_after INT DEFAULT 0;
     set nid= NodeID;
     delete from CHILD_TABLE;
     insert into CHILD_TABLE values (nid);
     set rows_before = (select count(*) from CHILD_TABLE);
     if rows_before !=rows_after then
       increment: repeat
        set rows_before = (select count(*) from CHILD_TABLE);
        insert ignore into CHILD_TABLE (nodeid) select b.nodeid from CORPORATENODE b 
        where b.parentid in (select c.nodeid from CHILD_TABLE c);
        set rows_after= (select count(*) from CHILD_TABLE);
        until rows_before =rows_after
       end repeat increment;
    end if;
    update NODEVERSION n set STATUS=1 where n.nodeid in 
    (select c.nodeid from CHILD_TABLE c);
   END
person GalwayGirl    schedule 30.11.2011