مقدمه :

تابع LISTAGG در نسخه 11GR2 معرفی شد که هدف آن تجمیع چند رشته ( چند رکورد ) در یک رشته می باشد. اوراکل در نسخه 12CR2 قابلیت جدیدی را به این تابع اضافه کرده که در مواقعی خروجی چند رشته طول زیادی داشته باشد و این تابع با خطا مواجه می شود، قابل استفاده می باشد. (ON OVERFLOW Handling)

تابع LISTAGG در اوراکل 12cr2

ایجاد مشکل و حل آن :

COLUMN employees FORMAT A40

SELECT deptno, LISTAGG(ename, ‘,’) WITHIN GROUP (ORDER BY ename) AS employees

FROM   emp

       CROSS JOIN (SELECT level FROM dual CONNECT BY level <= 1000)

WHERE  deptno = 30

GROUP BY deptno

ORDER BY deptno;

FROM   emp

       *

ERROR at line 2:

ORA-01489: result of string concatenation is too long

همانطور که قابل مشاهده است، خروجی بالا با خطا مواجه شده است که علت آن طول زیاد رشته خروجی می باشد. در نسخه 12CR2 قابلیت ON OVERFLOW اضافه شده که به صورت پیش فرض ON OVERFLOW ERROR می باشد.

COLUMN employees FORMAT A40SELECT deptno, LISTAGG(ename, ‘,’ ON OVERFLOW ERROR) WITHIN GROUP (ORDER BY ename) AS employeesFROM   emp       CROSS JOIN (SELECT level FROM dual CONNECT BY level <= 1000)WHERE  deptno = 30GROUP BY deptnoORDER BY deptno;

 FROM   emp       *ERROR at line 2:ORA-01489: result of string concatenation is too long

SQL>

حل مشکل با قابلیت ON OVERFLOW :

برای حل این مشکل باید از قابلیت ON OVERFLOW TRUNCATE استفاده کرد. به مثال زیر توجه کنید.

COLUMN employees FORMAT A70

SELECT deptno, LISTAGG(ename, ‘,’ ON OVERFLOW TRUNCATE) WITHIN GROUP (ORDER BY ename) AS employeesFROM   emp       CROSS JOIN (SELECT level FROM dual CONNECT BY level <= 1000)WHERE  deptno = 30GROUP BY deptnoORDER BY deptno;

DEPTNO EMPLOYEES———- ———————————————————————-        30 ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLE           N,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,AL           LEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,[removed]           N,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,AL           LEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,…(5339)

 SQL>

در این حالت می توان حتی عبارت (…) را تغییر داد

COLUMN employees FORMAT A70

SELECT deptno, LISTAGG(ename, ‘,’ ON OVERFLOW TRUNCATE ‘~~~’) WITHIN GROUP (ORDER BY ename) AS employeesFROM   emp       CROSS JOIN (SELECT level FROM dual CONNECT BY level <= 1000)WHERE  deptno = 30GROUP BY deptnoORDER BY deptno;

DEPTNO EMPLOYEES———- ———————————————————————-        30 ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLE           N,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,AL           LEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,[removed]           N,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,AL           LEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,~~~(5339)

SQL>

ما حتی می توانیم مقدار مربوط به تعداد را که در انتها رشته اضافه شده را حذف کنیم.

COLUMN employees FORMAT A70

 SELECT deptno, LISTAGG(ename, ‘,’ ON OVERFLOW TRUNCATE ‘…’ WITHOUT COUNT) WITHIN GROUP (ORDER BY ename) AS employeesFROM   emp       CROSS JOIN (SELECT level FROM dual CONNECT BY level <= 1000)WHERE  deptno = 30GROUP BY deptnoORDER BY deptno;

DEPTNO EMPLOYEES———- ———————————————————————-        30 ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLE           N,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,AL           LEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,[removed]           N,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,AL           LEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,ALLEN,

 SQL>