Oracle SQL: 인라인 뷰에 있을 때 SYS_GUID()의 동작을 이해하시겠습니까?
다음은 문제의 SQL 예제입니다.SQL은 모든 Oracle DBMS에서 실행되어야 합니다(11.2.0.2.0 실행 중).
인라인 뷰/with 절 내에서 빌드되었음에도 불구하고 결과 집합에서 UUID 값이 어떻게 다른지(하나는 898개이고 다른 하나는 899개임)에 주목합니다.아래에서 DBMS_RANDOM.RANDOM()이 이러한 부작용을 일으키지 않는 방법을 확인할 수 있습니다.
SQL:
WITH data AS (SELECT SYS_GUID () uuid FROM DUAL)
SELECT uuid, uuid
FROM data
출력:
UUID UUID_1
F8FCA4B4D8982B55E0440000BEA88F11 F8FCA4B4D8992B55E0440000BEA88F11
대조적으로 DBMS_RANDOM 결과는 동일합니다.
SQL:
WITH data AS (SELECT DBMS_RANDOM.RANDOM() rand FROM DUAL)
SELECT rand, rand
FROM data
출력:
RAND RAND_1
92518726 92518726
더욱 흥미로운 것은 DBMS_RANDOM.RANDOM.RANDOM:
WITH data AS (
SELECT SYS_GUID () uuid,
DBMS_RANDOM.random () rand
FROM DUAL)
SELECT uuid a,
uuid b,
rand c,
rand d
FROM data
SYS_GUID를 안정화하는 SQL Fiddle: http://sqlfiddle.com/ #!4/d41d8/29409
이상한 SYS_GUID 동작을 보여주는 SQL Fiddle: http://sqlfiddle.com/ #!4/d41d8/29411
이 문서는 불일치(내 항목 강조)를 볼 수 있는 이유를 제공합니다.
주의:
SQL은 명령형(또는 절차형) 언어가 아닌 선언형 언어이기 때문에 명령형 언어인 PL/SQL로 작성된 경우에도 SQL 문에 의해 호출된 함수가 실행되는 횟수를 알 수 없습니다.응용 프로그램에서 특정 횟수만큼 함수를 실행해야 하는 경우 SQL 문에서 해당 함수를 호출하지 마십시오.대신 커서를 사용합니다.
예를 들어, 프로그램에서 선택한 각 행에 대해 함수를 호출해야 하는 경우 커서를 열고 커서에서 행을 선택한 다음 각 행에 대한 함수를 호출합니다.이 기법은 함수에 대한 호출 수가 커서에서 가져온 행 수임을 보장합니다.
기본적으로 Oracle은 sql 문 안에서 함수가 호출되는 횟수를 지정하지 않습니다. 릴리스, 환경, 액세스 경로 등에 따라 다를 수 있습니다.
그러나 중첩된 하위 쿼리의 중첩 해제 장에서 설명한 대로 쿼리 다시 쓰기를 제한하는 방법이 있습니다.
하위 쿼리는 하위 쿼리 본문을 포함하는 문 본문에 병합하여 최적화 도구가 액세스 경로 및 조인을 평가할 때 함께 고려할 수 있도록 합니다.최적화 도구는 일부 예외를 제외하고 대부분의 하위 쿼리를 중첩 해제할 수 있습니다.이러한 예외에는 ROWNUM 유사 열, 집합 연산자 중 하나, 중첩 집계 함수 또는 하위 쿼리의 직접 외부 쿼리 블록이 아닌 쿼리 블록에 대한 상관 참조가 포함되는 계층적 하위 쿼리와 하위 쿼리가 포함됩니다.
위에서 설명한 대로 유사 열을 사용하여 Oracle이 하위 쿼리를 제거하지 못하도록 할 수 있습니다.
SQL> WITH data AS (SELECT SYS_GUID() uuid FROM DUAL WHERE ROWNUM >= 1)
2 SELECT uuid, uuid FROM data;
UUID UUID
-------------------------------- --------------------------------
1ADF387E847F472494A869B033C2661A 1ADF387E847F472494A869B033C2661A
NO_MERGE 힌트는 이를 "수정"합니다.오라클이 인라인 보기를 다시 쓰지 못하도록 합니다.
WITH data AS (SELECT /*+ NO_MERGE */
SYS_GUID () uuid FROM DUAL)
SELECT uuid, uuid
FROM data
NO_MERGE 힌트는 옵티마이저에게 외부 쿼리와 인라인 뷰 쿼리를 단일 쿼리로 결합하지 않도록 지시합니다.이 힌트를 사용하면 보기에 액세스하는 방식에 더 많은 영향을 줄 수 있습니다.
다음과 같은 방식으로 쿼리를 다시 작성하는 방법을 이해하기 위해 여전히 노력하고 있습니다.sys_guid()
두 번 호출됩니다.아마도 그것은 버그일 것입니다; 하지만 저는 그것이 제 생각/코드상 버그라고 생각하는 경향이 있습니다.
매우 흥미롭습니다.
구체화 힌트를 사용하여 수정할 수 있습니다.
WITH data AS (SELECT /*+materialize*/SYS_GUID () uuid FROM DUAL)
SELECT uuid, uuid
FROM data;
1 F9440E2613761EC8E0431206460A934C F9440E2613761EC8E0431206460A934C
제 입장에서는 힌트를 추가하는 것만으로 쿼리 결과를 변경할 수 있다면 오라클 버그가 있습니다.메탈링크에 확인을 요청해야 할 수도 있습니다.
언급URL : https://stackoverflow.com/questions/23572605/oracle-sql-understanding-the-behavior-of-sys-guid-when-present-in-an-inline-v
'programing' 카테고리의 다른 글
두 개의 다른 막대 열의 연결을 나타내는 열 추가 (0) | 2023.07.06 |
---|---|
VBA에서 사용되지 않는 변수를 알 수 있는 방법이 있습니까? (0) | 2023.07.06 |
'_body' 속성이 'Response' 유형에 없습니다. (0) | 2023.07.06 |
Android에서 Firebase를 사용하려면 어떤 ProGuard 구성이 필요합니까? (0) | 2023.07.06 |
WordPress 오류:웹 사이트에 심각한 오류가 발생했습니다.지침은 사이트 관리자 전자 메일 받은 편지함을 확인하십시오. (0) | 2023.07.06 |