Oracle SYS_CONNECT_BY_PATH que alcanza el límite de 4000 caracteres
Pregunta
Me gustaría ejecutar una consulta como la que se muestra a continuación en una base de datos Oracle 9i desde Java (a continuación se muestra una estructura de tabla de ejemplo y los datos de ejemplo).
SELECT deptno , SUBSTR(comma_list, 2) comma_list FROM (SELECT deptno , SYS_CONNECT_BY_PATH(ename, ',') comma_list , row_number , row_count FROM (SELECT deptno , ename , ROW_NUMBER()OVER(PARTITION BY deptno ORDER BY empno) row_number , COUNT(*)OVER(PARTITION BY deptno) row_count FROM wd_emp) START WITH row_number = 1 CONNECT BY deptno = PRIOR deptno AND row_number = PRIOR row_number + 1) WHERE row_number = row_count;
Esto funciona bien. Sin embargo, si el sys_connect_by_path que construye comma_list alcanza el límite de caracteres varchar2 4000, entonces obtengo un " ORA-01489: el resultado de la concatenación de cadenas es demasiado largo " error.
¿Alguien tiene alguna sugerencia sobre cómo superar este límite para que mi concatenación pueda exceder los 4000 caracteres?
Tablas y datos de ejemplo:
CREATE TABLE WD_DEPT(DEPTNO NUMBER(2) CONSTRAINT PK_DEPT PRIMARY KEY ,DNAME VARCHAR2(14) ,LOC VARCHAR2(13)); CREATE TABLE WD_EMP(EMPNO NUMBER(4) CONSTRAINT PK_EMP PRIMARY KEY ,ENAME VARCHAR2(10) ,JOB VARCHAR2(10) ,MGR NUMBER(4) ,HIREDATE DATE ,SAL NUMBER(7,2) ,DEPTNO NUMBER(2) CONSTRAINT FK_DEPTNO REFERENCES WD_DEPT); INSERT INTO WD_DEPT VALUES(10,'TEAM GREGORY','TABLE 3'); INSERT INTO WD_DEPT VALUES(20,'TEAM HANLEY','TABLE 2'); INSERT INTO WD_DEPT VALUES(30,'TEAM OFFIAH','TABLE 4'); INSERT INTO WD_DEPT VALUES(40,'TEAM BOTICA','TABLE 1'); INSERT INTO WD_DEPT VALUES(50,'TEAM SKERRETT','TABLE 4'); INSERT INTO WD_DEPT VALUES(60,'TEAM McGINTY','TABLE 1'); INSERT INTO WD_DEPT VALUES(70,'EMPTY TEAM','NO TABLE'); INSERT INTO WD_EMP VALUES(11,'GREGORY', 'TEAM LEAD', 28, to_date('18-JAN-2000', 'DD-MON-RRRR'), 800, 10); INSERT INTO WD_EMP VALUES(12,'BELL', 'DEVELOPER', 11, to_date('17-JAN-2000', 'DD-MON-RRRR'), 600, 10); INSERT INTO WD_EMP VALUES(13,'CLARKE', 'DEVELOPER', 11, to_date('16-JAN-2000', 'DD-MON-RRRR'), 600, 10); INSERT INTO WD_EMP VALUES(14,'HANLEY', 'TEAM LEAD', 28, to_date('15-JAN-2000', 'DD-MON-RRRR'), 800, 20); INSERT INTO WD_EMP VALUES(15,'BETTS', 'CONTRACTOR', 14, to_date('14-JAN-2000', 'DD-MON-RRRR'), 700, 20); INSERT INTO WD_EMP VALUES(16,'MILES', 'CONTRACTOR', 14, to_date('13-JAN-2000', 'DD-MON-RRRR'), 700, 20); INSERT INTO WD_EMP VALUES(17,'HAMPSON', 'DEVELOPER', 14, to_date('12-JAN-2000', 'DD-MON-RRRR'), 600, 20); INSERT INTO WD_EMP VALUES(18,'PRESTON', 'DEVELOPER', 14, to_date('11-JAN-2000', 'DD-MON-RRRR'), 600, 20); INSERT INTO WD_EMP VALUES(19,'OFFIAH', 'TEAM LEAD', 28, to_date('10-JAN-2000', 'DD-MON-RRRR'), 800, 30); INSERT INTO WD_EMP VALUES(20,'PLATT', 'DEVELOPER', 19, to_date('09-JAN-2000', 'DD-MON-RRRR'), 600, 30); INSERT INTO WD_EMP VALUES(21,'POTTER', 'DEVELOPER', 19, to_date('08-JAN-2000', 'DD-MON-RRRR'), 600, 30); INSERT INTO WD_EMP VALUES(22,'CASE', 'DEVELOPER', 19, to_date('07-JAN-2000', 'DD-MON-RRRR'), 600, 30); INSERT INTO WD_EMP VALUES(23,'BOTICA', 'TEAM LEAD', 28, to_date('06-JAN-2000', 'DD-MON-RRRR'), 800, 40); INSERT INTO WD_EMP VALUES(24,'GILL', 'DEVELOPER', 23, to_date('05-JAN-2000', 'DD-MON-RRRR'), 600, 40); INSERT INTO WD_EMP VALUES(25,'SKERRETT', 'TEAM LEAD', 28, to_date('04-JAN-2000', 'DD-MON-RRRR'), 800, 50); INSERT INTO WD_EMP VALUES(26,'McGINTY', 'TEAM LEAD', 28, to_date('03-JAN-2000', 'DD-MON-RRRR'), 800, 60); INSERT INTO WD_EMP VALUES(27,'LOWE', 'MANAGER', 28, to_date('02-JAN-2000', 'DD-MON-RRRR'), 900, NULL); INSERT INTO WD_EMP VALUES(28,'MONIE', 'MANAGER', NULL, to_date('01-JAN-2000', 'DD-MON-RRRR'), 1000, NULL);
Solución
¿Es necesario construir la lista de comas en SQL?
Como está ejecutando esto desde Java de todos modos, tal vez podría consultar filas con '' parent_id '' , " child_id " ;, " tree_level " columnas y construir la ruta del empleado en su código de aplicación? Supongo que ahora lo estás dividiendo en una Lista (una cadena de 4000 caracteres no puede ser para fines de visualización directa).
Otros consejos
Dos ideas:
-
no concatene las cadenas reales, sino marcadores de posición más cortos y use algún método de reemplazo (en java o de otro modo) para insertar los nombres reales
-
podría crear múltiples columnas: comma_list_ donde cada una contiene el enésimo grupo de 400 empleados. El valor final resultaría de concatinar estas columnas en el cliente.
Estaba entendiendo que el límite de 4000 caracteres para varchar2 era solo para columnas, que las longitudes de varchar2 en realidad se permitían MUCHO más grandes, por ejemplo en PL / SQL. ¿Está seguro de que su consulta no es recurrente y genera un producto cartesiano grande?