PL / pgSQL에서 쿼리가 결과를 반환하지 않았는지 확인하는 간단한 방법이 있습니까?


16

나는 현재 PL / pgSQL을 약간 실험하고 있으며 다음과 같이 더 우아한 방법이 있는지 알고 싶습니다.

select c.data into data from doc c where c.doc_id = id and c.group_cur > group_cur order by c.id desc limit 1;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        select c.data into data from doc c where c.doc_id = id and c.global_cur > global_cur order by c.id desc limit 1;
        EXCEPTION
            WHEN NO_DATA_FOUND THEN
                RETURN NULL;

답변:


21

예외 블록은 조건을 확인하지 않고 트래핑 오류를 의미합니다. 즉, 컴파일시 일부 조건을 처리 할 수 ​​있으면 오류로 잡히지 말고 일반적인 프로그램 로직으로 해결해야합니다.

에서 PL / pgSQL의 문서의 트래핑 오류 섹션 당신은 끝을 찾을 수 있습니다 :

팁 : EXCEPTION 절을 포함하는 블록은 블록이없는 블록보다 들어오고 나가는 데 훨씬 더 비쌉니다. 따라서 필요없이 EXCEPTION을 사용하지 마십시오.

예외 (나쁜) 또는 IF / THEN / ELSIF (더 나은)를 사용하는 대신이를 하나의 쿼리로 다시 작성할 수 있습니다.

SELECT c.data into data
FROM  doc c
WHERE c.doc_id = id
  and (
    c.group_cur > group_cur
    or
    c.global_cur > global_cur
  )
ORDER BY
  -- this will make group always preferred over global
  case when c.group_cur > group_cur then 1 else 2 end ASC,
  -- and this is your normal ordering
  c.id DESC
limit 1;

실제로 두 개의 쿼리를 원할 경우 특수 FOUND 변수를 사용하여 이전 쿼리에 결과가 있는지 테스트 할 수 있습니다.

select c.data into data
from doc c
where c.doc_id = id and c.group_cur > group_cur
order by c.id desc limit 1;
if not found then
    select c.data into data
    from doc c
    where c.doc_id = id and c.global_cur > global_cur
    order by c.id desc limit 1;
    if not found then return null; end if;
end if;

의무적 인 RTFM 링크는 다음과 같습니다 :-)

참조 의 설명 FOUND변수 및 에 대한 IF/ THEN블록.


13

부울 유형의 특수 변수 FOUND를 검사 할 수 있습니다. 설명서에서 :

FOUND는 각 PL / pgSQL 함수 호출 내에서 false를 시작합니다. 다음 각 유형의 명령문으로 설정됩니다.

SELECT INTO 문은 행이 지정되면 FOUND를 true로 설정하고 행이 리턴되지 않으면 false를 설정합니다.

PERFORM 문은 하나 이상의 행을 생성하고 버릴 경우 FOUND를 true로 설정하고 행이 생성되지 않으면 false를 설정합니다.

UPDATE, INSERT 및 DELETE 문은 하나 이상의 행이 영향을받는 경우 FOUND를 true로 설정하고 행이 영향을받지 않으면 false를 설정합니다.

FETCH 문은 행을 리턴하면 FOUND를 true로 설정하고 행이 리턴되지 않으면 false를 설정합니다.

MOVE 문은 커서를 성공적으로 재배치하면 FOUND를 true로 설정하고 그렇지 않으면 false를 설정합니다.

FOR 또는 FOREACH 문은 FOUND가 한 번 이상 반복되면 true를 설정하고 그렇지 않으면 false를 설정합니다. 루프가 종료 될 때 FOUND는 이런 식으로 설정됩니다. 루프 실행 내에서 루프 본문 내에서 다른 명령문의 실행에 의해 변경 될 수 있지만 FOUND는 루프 문에 의해 수정되지 않습니다.

RETURN QUERY 및 RETURN QUERY EXECUTE 문은 쿼리가 하나 이상의 행을 리턴하면 true를 설정하고 행이 리턴되지 않으면 false를 설정합니다.

다른 PL / pgSQL 문은 FOUND 상태를 변경하지 않습니다. 특히 EXECUTE는 GET DIAGNOSTICS의 출력을 변경하지만 FOUND는 변경하지 않습니다.

FOUND는 각 PL / pgSQL 함수 내의 지역 변수입니다. 변경 사항은 현재 기능에만 영향을줍니다.


그러나 select into데이터를 반환하지 않으면 여전히 예외가 발생합니다.
잭 topanswers.xyz 시도라고

3
일반적으로 아니요, SELECT * INTO STRICT my record와 같은 STRICT 절이 지정된 경우에만 예외가 발생합니다.
alexk

아 그래, 내 나쁜-OP 예제의 예외 처리기가 절대로 실행되지 않는다는 것을 의미하지는 않습니까? :-)
잭은 말한다 topanswers.xyz 시도

1
@JackDouglas : 데이터가 일반적으로 예외의 원인이 아닙니다 (위의 STRICT 수정 자와 같은 특수한 경우 제외). OP에는 오해가 있었다.
Erwin Brandstetter
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.