Inizialmente, non potevo vedere una soluzione più elegante che creare una tabella temporanea.
Stavo pensando, che dialetto imbarazzante di SQL Oracle è:
- Perché no SE LA TABELLA ESISTE ELIMINA TABELLA?
- Perché devo eseguire ESEGUI IMMEDIATO con una stringa? Perché non posso fare da solo DROP TABLE TEMP?
- Perché non posso avere ORDER BY senza annidare tra parentesi su ANCHOR?
- Perché non posso avere ORDER BY su SELECT ricorsivo dopo UNION ALL?
- SQL WITH necessita di standardizzazione. Altri dialetti del database non richiedono che i nomi delle colonne siano tra parentesi nell'istruzione WITH. Se non lo fai, ottieni un errore ALIAS senza significato, al punto del join ricorsivo dopo UNION ALL.
- Impaginazione:vedi qui Nessun LIMITE / 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;
Quindi (mathguy sull'Oracle Community Forum) mi ha fatto notare che il mio SEARCH DEPTH FIRST avrebbe dovuto essere appena JOBMST_NAME.
Poi tutto va a posto:
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