最初,我看不到比创建临时表更好的解决方案。
我当时在想,SQL Oracle的尴尬方言是:
- 为什么没有IF表存在删除表?
- 为什么必须对字符串执行EXECUTE IMMEDIATE?为什么我不能仅自己做DROp TABLE TEMP?
- 为什么没有嵌套在ANCHOR上的括号内就不能拥有ORDER BY?
- 为什么在UNIOn ALL之后不能对递归SELECT进行ORDER BY?
- SQL WITH需要标准化。其他数据库方言不需要在WITH语句上用括号括起来的列名。如果不这样做,则会在UNIOn ALL之后的递归联接时出现一些毫无意义的ALIAS错误。
DECLARE v_c NUMBER;BEGINSELECT 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 ALLSELECt J2.JOBMST_ID, J2.JOBMST_NAME, J2.JOBMST_PRNTID, J2.JOBMST_TYPE, J1.LVL + 1FROM TEMP J2INNER JOIN J1 ON J2.JOBMST_PRNTID = J1.JOBMST_IDWHERe J2.JOBMST_PRNTID IS NOT NULL)SEARCH DEPTH FIRST BY JOBMST_ID SET DISP_SEQSELECt *FROM J1ORDER BY DISP_SEQ;
然后(Oracle社区论坛上的mathguy)向我指出,我的SEARCH
DEPTH FIRST应该只是JOBMST_NAME。
然后一切都就位了:
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 NULLUNIOn ALLSELECt J2.JOBMST_ID, J2.JOBMST_NAME, J2.JOBMST_PRNTID, J2.JOBMST_TYPE, J1.LVL + 1FROM TIDAL.JOBMST J2INNER JOIN J1 ON J2.JOBMST_PRNTID = J1.JOBMST_IDWHERe J2.JOBMST_PRNTID IS NOT NULL)SEARCH DEPTH FIRST BY JOBMST_NAME SET DISP_SEQSELECt *FROM J1ORDER BY DISP_SEQ



