2012-03-26 2 views
0

복잡한 논리를 캡슐화하기 위해 저장된 proc 파일을 빌드하려고합니다. 다음은 익명으로 처리 한 기본 코드입니다.왜이 저장 프로 시저가 빈 집합을 반환합니까?

SET TERM^; 

RECREATE PROCEDURE GET_DATA (
USERID INTEGER, 
W  INTEGER, 
X  INTEGER, 
Y  INTEGER) 
RETURNS (
ID  INTEGER, 
NAME  VARCHAR(64) CHARACTER SET UTF8) 
AS 
BEGIN 
    select first 1 
    QP.ID, 
    QO.NAME 
    from QP 
    join QO 
    on QO.ID = QP.QO_ID 
    where 
    (QO.W = :w) and (QO.X = :x) and (QO.Y = :y) 
    and ((QP.PREREQUISITE in (
     select VALUE 
     from LOOKUP_TABLE1 
     where USER_ID = :userid)) 
     or (QP.PREREQUISITE is null)) 
    and (QO.Q_ID not in (
     select VALUE 
     from LOOKUP_TABLE2 
     where USER_ID = :userid)) 
    order by QP.SEQUENCE desc 
    into :ID, :NAME; 
    suspend; 
END^ 

SET TERM ;^

결과가 1 또는 0을 반환 할 것으로 예상됩니다. 그것은 논리적으로 정확합니다. SELECT 쿼리를 사용하면 수동으로 매개 변수를 대체하고 Firebird Maestro에서 실행하면 예상되는 결과가 나타납니다. 그러나 동일한 매개 변수를 사용하여 select ID, NAME from GET_DATA(1, 1, 2, 3)이라고 말하면 빈 결과 집합이 반환됩니다.

그래서 저장 프로 시저 수준에서 문제가 발생합니다. 누구나 그게 뭔지 알 수 있고 어떻게 고칠 수 있니?

+0

이 LOOKUP_TABLE2.VALUE''null 허용 필드인가? 왜냐하면 ''의 결과 세트가 'NULL'을 포함하면 ' NOT IN ()'이 참일 수 있기 때문입니다. (그게 문제라면, 문제는 서브 쿼리에'VALUE is not null'을 추가하는 것입니다.) – ruakh

+0

@ruakh : 아니요, 두 룩업 테이블에는 NULL 제약 조건이 없습니다. 내가 말했듯이, 쿼리는 논리적으로 정확합니다. 저장 프로 시저로 실행할 때 어떤 결과도 실행되지 않습니다. –

+1

@Mason이 테이블과 일부 샘플 데이터를 DDL 상태로 게시하여 다시 만들 수 있으면 좋을 것입니다 - SP는 괜찮은 것 같습니다 – JustMe

답변

0

당신은 이것을 선택 가능한 절차로 취급하지만, 파이어 버드는 이것이 선택 가능한 절차가 아니라 실행 가능한 절차라고 봅니다. 끝 부분에 SUSPEND을 추가하면 AFAIK가 문제를 해결합니다.

+0

Nope. 나는 그것을 시도하고, 그것은 작동하지 않았다. 나는 그 질문을 갱신 할 것이다. –

+0

[이 페이지] (http://www.destructor.de/firebird/storedproc.htm)는'SUSPEND'가 실제로'SELECT' 이전에 있어야한다는 것을 의미합니까? – ruakh

+0

@ruakh'SUSPEND'는 반환 변수를 "출력합니다"그리고 그것들이 비어 있기 전에 선택합니다. – JustMe

0

SUSPEND은 마치 "결과로 선 보내기"를 의미하는 거꾸로 FETCH과 같습니다.

4 줄을 SUSPEND와 함께 추가하면; GET_DATA (매개 변수)에서 select *를 수행 한 결과는 널 (null) 값이있는 최소한 4 행이어야합니다. 이는 select 문이 아무런 행도 반환하지 않았거나 null 값을 가진 하나의 행을 반환했음을 의미합니다.

더 간단한 쿼리로 몇 가지 테스트를 수행하십시오.

select 1, 'TEST' from RDB$DATABASE into :ID, :NAME;

2

귀하의 절차는 항상 선택을 반환 1 또는 0 결과 때문에 선택의 독립적 인 SUSPEND 경우에도 한 결과를 반환합니다.

0 또는 1이 해당 결과를 선택 얻으려면, 당신은 사용할 수 있습니다

RECREATE PROCEDURE GET_DATA (
    USERID INTEGER, 
    W  INTEGER, 
    X  INTEGER, 
    Y  INTEGER) 
    RETURNS (
    ID  INTEGER, 
    NAME  VARCHAR(64) CHARACTER SET UTF8) 
    AS 
    BEGIN 
    FOR select first 1 
     QP.ID, 
     QO.NAME 
    from QP 
    join QO 
     on QO.ID = QP.QO_ID 
    where 
     (QO.W = :w) and (QO.X = :x) and (QO.Y = :y) 
     and ((QP.PREREQUISITE in (
     select VALUE 
     from LOOKUP_TABLE1 
     where USER_ID = :userid)) 
     or (QP.PREREQUISITE is null)) 
     and (QO.Q_ID not in (
     select VALUE 
     from LOOKUP_TABLE2 
     where USER_ID = :userid)) 
    order by QP.SEQUENCE desc 
    into :ID, :NAME DO 
     suspend; 
    END^ 

    SET TERM ;^
+0

1 또는 0 ** 결과 ** - nice :) – JustMe

+0

하지만 항상 결과가 하나가 아닙니다. 나는이 쿼리를 실행할 때 항상 빈 세트 (0 결과)를 얻고있다. 그런 루프를 for 루프로 바꾸면 도움이되지 않습니다. –

관련 문제