2011-09-01 1 views
1

, 나는이 쿼리를 (의 더 큰 버전)을 실행하고 슈퍼 사용자가/관리자가 내 시스템에 로그인 할 수 있도록하려면 다음Oracle 기능과의 단락 OR이 없습니까?

Select * 
    From mytable 
Where (:id = 'Admin' Or :id = mytable.id); 

내가 해당 사용자의 모든 데이터를 얻을 수있는 사용자 ID를 전달하는 경우; 'Admin'문자열을 전달하면 모두 데이터를 얻습니다. 오라클의 OR은 short-circuit operator이므로 작동합니다. 내가 '관리'를 통과 할 때이

Select * 
    From mytable 
Where (:id = mypackage.GetAdminConstant Or :id = mytable.id); 

같은 그러나

, 내가 '관리자'패키지 일정하게하고 기능을 얻는 경우에, 나는 ORA-01722: invalid number 얻을.

기능을 도입 할 때 OR이 단락 회로를 잃는 이유는 무엇입니까?

+0

중복 가능성 [최신 DBMS는 단락 불리언 평가를 포함 하는가? (http://stackoverflow.com/questions/6960767/do-modern-dbms-include-short-circuit-boolean-evaluation) –

+0

아닙니다. 내가 찾을 수있는 문서는 그것이 단락되었음을 말한다. 이것은 규칙의 예외 인 것처럼 보입니다. 이유를 알고 싶습니다. –

+0

': id' (바인드일까요?)이고 어떤 타입이'mypackage.GetAdminConstant'입니까? –

답변

6

단락 회로가 손실되지 않습니다. 그러나 SQL은 프로 시저 언어가 아니며 다중 술어의 평가 순서에 대한 보장이 없습니다.

C에서 a || b으로 작성하면 a이 먼저 평가되고, b은 필요한 경우에만 평가된다는 것을 알게됩니다.

a OR b으로 작성하면 a 또는 b 중 하나가 먼저 평가되고 다른 표현식 (최소한 Oracle에서는)은 필요한 경우에만 평가된다는 것을 알고 있습니다.

두 개의 쿼리에 대한 실행 계획을 보면 평가 순서가 일부 표시 될 수도 있고 그렇지 않을 수도 있습니다.

첫 번째 경우, 오라클은 첫 번째 표현식이 모든 행에 대해 동일한 값을 가지므로 먼저 평가할 것입니다. 두 번째 케이스로 변경하면 Oracle은 이제 평가 될 때마다 다른 결과를 가질 수있는 함수를 보게되므로 각 행을 검사해야하므로 함수 호출을 수행하기 전에 열에 대한 간단한 동일성 검사를 시도합니다 .

DETERMINISTIC 함수를 표시하면 오라클이 본질적으로 상수라는 것을 알 수 있으므로 다른 결과가 나올지 궁금합니다.

+0

직접 (schema.package.constant) 상수에 액세스하려고하면 'MYCONSTANT가 프로 시저가 아니거나 정의되지 않았습니다.'라는 메시지가 나타납니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까? –

+0

아, 위에서 링크 된 문서는 SQL이 아닌 PL/SQL 용입니다. 그리고 저는 제 실행 계획을 점검했습니다 : 당신 말이 맞았습니다. 그것은 두 쿼리 사이에서 평가 순서를 전환합니다. 불행한 사람. –

+0

@Brian - 죄송합니다. 실제로 SQL에서 패키지 상수를 직접 사용할 수없는 것처럼 보입니다. 내 대답에서 그 제안을 삭제했습니다. –

1

2 개의 바인드 변수를 사용하는 것이 좋습니다.

Select * 
    From mytable 
Where (:admin = 'Admin' Or (:admin is null and :id = mytable.id));