2009-05-01 7 views
2

Ich möchte eine Abfrage wie die unten gegen eine Oracle 9i-Datenbank von Java (eine Beispieltabellenstruktur und Beispieldaten sind unten) ausführen.Oracle SYS_CONNECT_BY_PATH trifft 4000 Zeichen Grenze

 
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; 

Das funktioniert gut. Wenn jedoch der sys_connect_by_path, der comma_list aufbaut, die varchar2 4000 Zeichen Grenze erreicht, dann bekomme ich eine "ORA-01489: Ergebnis der String-Verkettung ist zu lang" Fehler.

Hat jemand irgendwelche Vorschläge, wie man dieses Limit überwinden kann, so dass meine Verkettung 4000 Zeichen überschreiten kann?

Tabellen und Beispieldaten:

 

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); 

Antwort

2

Ist es notwendig, die durch Komma Liste in SQL zu bauen?

Da Sie dies sowieso von Java aus ausführen, könnten Sie vielleicht Zeilen mit den Spalten "parent_id", "child_id", "tree_level" abfragen und den Mitarbeiterpfad in Ihrem Anwendungscode erstellen? Ich nehme an, Sie teilen es jetzt in eine Liste auf (eine 4000 Zeichen lange Zeichenfolge kann nicht für direkte Anzeigezwecke verwendet werden).

+0

Ich muss alles zusammen verketten, um auf einer dateibasierten Schnittstelle gesendet werden. Wie du sagst, kann ich stattdessen mehrere Zeilen ziehen, über diejenigen in Java iterieren und verketten. Aber ich fragte mich, ob ich alles mit einem Schlag in die DB schaffen könnte. –

+0

Ich denke nicht, dass es in Bezug auf die Leistung sinnvoll ist. Sie würden auch viel mehr Daten als nötig über die Leitung senden. Aber es ist eine interessante Übung. Google "STRAGG" oder "sys_connect_by_path" für mehrere Ansätze zu dem Problem. Es kann gemacht werden, um mit CLOB zu arbeiten, glaube ich. – Thilo

0

Zwei Ideen:

  • Sie die aktuellen Strings nicht verketten, aber kürzer Platzhalter und einige Verfahren ersetzen verwenden (in Java oder auf andere Weise), um die echten Namen einfügen

  • Sie mehrere Spalten erstellen können : comma_list_, wo jeder die n-te Gruppe von 400 Mitarbeitern hält. Der endgültige Wert würde sich aus der Zusammenfassung dieser Spalten im Client ergeben.

0

Ich war zu verstehen, dass die 4000 Zeichenbegrenzung varchar2 nur für Spalten war - dass varchar2 Längen wurden tatsächlich viel größer, in PL/SQL zum Beispiel erlaubt zu gehen. Sind Sie sicher, dass Ihre Abfrage nicht fälschlicherweise rekursiv ist und ein großes kartesisches Produkt generiert?

Verwandte Themen