2011-11-21 2 views
3

주어진 노드에 대한 모든 하위 레코드를 반환하도록 설계된 간단한 MySQL 저장 프로 시저가 있습니다. 내 문제는이 수동으로 입력하면 적절한 결과를 반환합니다 -하지만 동일한 코드를 저장 프로 시저에 넣을 때 부모 ID를 반환합니다.명령 줄에 다른 결과를주는 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을의

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

간단한 질문입니다.이 질문은 windows에서 실행합니까? 귀하의 경우 엉망으로 보이고 그것은 기본 구성된 MySQL과 리눅스 시스템에서 잘 작동하지 않습니다. –

+0

귀하의 절차가 결정적이지 않습니다. 그 (부적절한) 지정자없이 시도하십시오. – pilcrow

답변

2

MySQL은 당신의 select nodeid from CORPORATENODE where parentid in (1006);

변경에 변수 NODEID 대신 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 ; 
+0

+1 멋진 찾기 (DETERMINISTIC을 떨어 뜨린 것에 대해 감사드립니다). – pilcrow

1

감사합니다 안드레아스 등,

난 그냥 게시 후 이에 대한 해결 방법을 발견했다. 하지만 내 솔루션을 게시 할 수 없습니다. 리눅스를 사용하지만 lower_case_table_names = 1을 설정하여 대소 문자를 구분하지 않습니다. (제 생각에는?)

Andreas, 노드에 대한 모든 하위 레코드를 다시 선택 했으므로 임시 테이블이 필요했습니다. 그런 다음 NODEVERSION 테이블의 모든 하위 레코드를 업데이트해야했습니다. 나는 NODEVERSION 테이블의 트리거를 통해 이것을 실행하고 호출 테이블 등을 업데이트 할 때 문제가 발생하여 새로운 CHILD_TABLE을 작성한 것입니다. 나는 간단하게 모든 내가 추가 된 않았다 별명은 ... (아래 코드는 위에서 약간 다릅니다 -

그래서 나는 예상대로 (!도에 ... 죄송 단락 기호 DETERMINISTIC을 떠나) 일 다음 발견 내 질문에 위의 코드)

별칭이 초기 문제를 해결 한 이유를 완전히 이해하지 못했지만 효과가있었습니다. 아마도 전문가가 그 이유를 알고 있습니까?

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