Oracle의 LISTAGG 기능과 관련하여 매우 특이한 동작을 경험했습니다.LISTAGG가 도달 할 수없는 사례 문에서 평가되고 실패합니다.
4000 개가 넘는 문자를 처리하는 경우 LISTAGG가 실패합니다.
저는 이것을 알고 있기 때문에 100 자 이상의 셀을 "너무 많습니다"라는 메시지로 바꾸려면 CASE 문을 사용했습니다.
CREATE TABLE EMP (
ID VARCHAR2(401),
DEP VARCHAR2(10)
);
INSERT INTO EMP VALUES (DBMS_RANDOM.string('A', 401), 'FOO'); -- Run exactly 9 times
INSERT INTO EMP VALUES (DBMS_RANDOM.string('A', 5), 'BAR'); -- Run 3 times
단순화를 술 들어, 카운트> (100) 내 특별한 경우를 무시하자, 바로 그 FOO는 제외해야한다고하고, BAR가 포함되어야한다. (10)에 FOO 부서에서 총을 가져, 단지 하나의 여분의 행을 추가,
그러나 :
SELECT DEP,
CASE
WHEN DEP = 'BAR' THEN
LISTAGG(ID, ',')
WITHIN GROUP (ORDER BY NULL)
OVER (PARTITION BY DEP)
ELSE
'Too many to count'
END AS ID_LIST
FROM EMP;
이 (다른 임의의 문자와 만)과 같아야 결과를 제공 ...
INSERT INTO EMP VALUES (DBMS_RANDOM.string('A', 401), 'FOO'); -- Same as before
선택 같은를 다시 실행 예외로 충족시킬 원인 :
ORA-01489: result of string concatenation is too long
01489. 00000 - "result of string concatenation is too long"
*Cause: String concatenation result is more than the maximum size.
*Action: Make sure that the result is less than the maximum size.
이상하게도 case 문에서 조건이 1 = 2로 변경된 경우에도 마찬가지입니다.
여기 무슨 일인지 잘 모르겠습니다. SQL은 사용 의도가 있는지 여부에 관계없이 명령문을 평가하기로 결정 했으므로 4000 + 문자 LISTAGG가 충족 될 때 실패합니다.
내 문제에 대한 몇 가지 해결책이 있지만 SQL에 도달하지 않아도 LISTAGG를 실행하도록 결정한 이유에 대해 자세히 알고 싶습니다.
case 문에서 첫 번째 'when'조건이 '1 = 0' 일 때 옵티마이 저가 더 나은 작업을 수행하지 않는다는 것은 여전히 이상합니다. 옵티마이 저는 case가 1 = 0이면 else를 '너무 많아서 end_id_list'로 재 작성해야 모든 것이 컴파일되기 전에 id_list'로'너무 많은 것으로 계산할 '수 있습니다. 옵티마이 저는 쿼리 구문 분석의 다른 부분에서 꽤 똑똑하지만이 경우에는 그렇지 않습니다. –
mathguy
문자열 비교 ('T'= 'F')가 아닌 숫자 비교 (1 = 0)를위한 최적화를 제안하는 MOS 메모가 있습니다. 그러나 그렇게하더라도 프로세스에서 너무 늦어야합니다 - 집계되지 않은 버전에서는 그렇게 할 것이지만 집계 등에 대해 걱정할 필요가있을 때 쿼리 재 작성의 규모가 너무 클 수도 있습니다. 어쩌면 너무 틈새 일 수 있습니다. 보았다 ... –
감사합니다 알렉스, 그건 아주 철저한 설명이었다. 나는 이것에 대한 설명을 할 생각을해야만했다. – Addison