Till en början kunde jag inte se en mer elegant lösning än att skapa ett tempbord.
Jag tänkte, vilken besvärlig dialekt av SQL Oracle är:
- Varför inte OM TABELL FINNS DELETE TABELL?
- Varför måste jag göra EXECUTE OMEDELBART med en sträng? Varför kan jag inte bara göra DROP TABLE TEMP på egen hand?
- Varför kan jag inte få ORDER BY utan att kapsla inom parentes på ANCHOR?
- Varför kan jag inte ha ORDER BY på rekursivt SELECT efter UNION ALL?
- SQL MED behöver standardiseras. Andra databasdialekter kräver inte att kolumnnamn sätts inom parentes på WITH-satsen. Om du inte gör det får du ett meningslöst ALIAS-fel, vid punkten för den rekursiva anslutningen efter UNION ALL.
- Sökning:Se här No LIMIT / OFFSET
DECLARE
v_c NUMBER;
BEGIN
SELECT COUNT(*) INTO v_c FROM user_tables WHERE TABLE_NAME = 'TEMP';
IF v_c = 1 THEN
EXECUTE IMMEDIATE 'DROP TABLE TEMP';
END IF;
END;
CREATE TABLE TEMP AS (
SELECT * FROM (
SELECT JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE
FROM TIDAL.JOBMST
WHERE JOBMST_PRNTID IS NOT NULL
ORDER BY JOBMST_PRNTID, JOBMST_NAME
)
);
WITH J1(JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, LVL) AS (
SELECT * FROM (
SELECT JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, 1
FROM TIDAL.JOBMST
WHERE JOBMST_PRNTID IS NULL
ORDER BY JOBMST_NAME
)
UNION ALL
SELECT J2.JOBMST_ID, J2.JOBMST_NAME, J2.JOBMST_PRNTID, J2.JOBMST_TYPE, J1.LVL + 1
FROM TEMP J2
INNER JOIN J1 ON J2.JOBMST_PRNTID = J1.JOBMST_ID
WHERE J2.JOBMST_PRNTID IS NOT NULL
)
SEARCH DEPTH FIRST BY JOBMST_ID SET DISP_SEQ
SELECT *
FROM J1
ORDER BY DISP_SEQ;
Sedan (mathguy på Oracle Community Forum) påpekade för mig att mitt SÖKDJUP FÖRST bara borde ha varit av JOBMST_NAME.
Då faller allt på plats:
WITH J1(JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, LVL) AS (
SELECT JOBMST_ID, JOBMST_NAME, JOBMST_PRNTID, JOBMST_TYPE, 1
FROM TIDAL.JOBMST
WHERE JOBMST_PRNTID IS NULL
UNION ALL
SELECT J2.JOBMST_ID, J2.JOBMST_NAME, J2.JOBMST_PRNTID, J2.JOBMST_TYPE, J1.LVL + 1
FROM TIDAL.JOBMST J2
INNER JOIN J1 ON J2.JOBMST_PRNTID = J1.JOBMST_ID
WHERE J2.JOBMST_PRNTID IS NOT NULL
)
SEARCH DEPTH FIRST BY JOBMST_NAME SET DISP_SEQ
SELECT *
FROM J1
ORDER BY DISP_SEQ