動態構建 SELECT col1, col2, ...、INSERT INTO t (col1, col2, ...)、比對兩表結構差異等,需將列名聚合為逗號分隔字符串。
SELECT MAX(SUBSTR(SYS_CONNECT_BY_PATH(COLUMN_NAME, ','), 2)) AS cols
FROM (
SELECT COLUMN_NAME, COLUMN_ID
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = UPPER('&表名')
)
START WITH COLUMN_ID = 1
CONNECT BY COLUMN_ID = PRIOR COLUMN_ID + 1;
SYS_CONNECT_BY_PATH(col, '/'):層次查詢函數,返回從根節點到當前節點的路徑字符串(如 /COL1/COL2/COL3)START WITH COLUMN_ID = 1:以第一列為根CONNECT BY COLUMN_ID = PRIOR COLUMN_ID + 1:按列 ID 遞歸串聯SUBSTR(..., 2):去除首字符分隔符MAX():取最深層級(最後一行)的完整路徑| 方法 | 版本要求 | 優點 | 缺點 |
|---|---|---|---|
LISTAGG(COLUMN_NAME, ',') WITHIN GROUP (ORDER BY COLUMN_ID) | 11gR2+ | 語法簡潔、性能好 | 舊版本不支持 |
WM_CONCAT(COLUMN_NAME) | 10g+ | 無需層次查詢 | 非文檔函數、可能被移除 |
XMLAGG(XMLELEMENT(...)).EXTRACT('//text()') | 9i+ | 標準 SQL/XML | 語法繁瑣 |
| PL/SQL 循環拼接 | 所有版本 | 邏輯可控 | 需寫函數/塊 |
CREATE OR REPLACE FUNCTION get_table_columns(p_table_name VARCHAR2)
RETURN CLOB IS
v_cols CLOB;
BEGIN
SELECT LISTAGG(COLUMN_NAME, ',') WITHIN GROUP (ORDER BY COLUMN_ID)
INTO v_cols
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = UPPER(p_table_name);
RETURN v_cols;
EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN NULL;
END;
/
-- 調用
SELECT get_table_columns('EMP') FROM DUAL;
-- 替換 USER_TAB_COLUMNS 為 ALL_TAB_COLUMNS 或 DBA_TAB_COLUMNS
SELECT ... FROM ALL_TAB_COLUMNS WHERE OWNER = 'SCOTT' AND TABLE_NAME = 'EMP'
Oracle 9i/10g 環境下,SYS_CONNECT_BY_PATH 是純 SQL 獲取逗號分隔列名的標準做法;11gR2+ 首選 LISTAGG。封裝為函數便於重複調用,提升開發效率。