將多行資料聚合為單一字串,例如:
-- 原始資料
DEPARTMENT ENAME
Marketing Hartstein
Marketing Fay
Purchasing Raphaely
Purchasing Khoo
-- 期望結果
DEPARTMENT EMPLOYEES
Marketing Hartstein,Fay
Purchasing Raphaely,Khoo
CREATE OR REPLACE FUNCTION concat_dept(p_dep IN VARCHAR2) RETURN VARCHAR2 IS
l_str VARCHAR2(200) DEFAULT NULL;
l_sep VARCHAR2(200) DEFAULT NULL;
BEGIN
FOR rc IN (SELECT ename FROM d_employee WHERE department = p_dep) LOOP
l_str := l_str || l_sep || rc.ename;
l_sep := ',';
END LOOP;
RETURN l_str;
END;
查詢用法:
SELECT d.department, concat_dept(d.department) employees
FROM d_employee d
GROUP BY d.department;
CREATE OR REPLACE FUNCTION concat_dyn(
p_key_name IN VARCHAR2, -- 條件欄位名
p_key_val IN VARCHAR2, -- 條件值
p_other_col IN VARCHAR2, -- 要聚合的欄位
p_table_name IN VARCHAR2 -- 來源表
) RETURN VARCHAR2 AS
TYPE rc_type IS REF CURSOR;
l_cur rc_type;
l_str VARCHAR2(4000);
l_sep VARCHAR2(200);
l_val VARCHAR2(4000);
BEGIN
OPEN l_cur FOR 'SELECT ' || p_other_col || ' FROM ' || p_table_name ||
' WHERE ' || p_key_name || ' = :x' USING p_key_val;
LOOP
FETCH l_cur INTO l_val;
EXIT WHEN l_cur%NOTFOUND;
l_str := l_str || l_sep || l_val;
l_sep := ',';
END LOOP;
CLOSE l_cur;
RETURN l_str;
END;
查詢用法:
SELECT d.department,
concat_dyn('department', d.department, 'ename', 'd_employee')
FROM d_employee d
GROUP BY d.department;
若聚合欄位值為固定有限集合(如'A','T','L'),可用DECODE/CASE配合MAX/WM_CONCAT(11g+)或LISTAGG(11gR2+)原生函數,效能更佳。
WM_CONCAT(非文件化)LISTAGG,LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename)JSON_ARRAYAGG等進階聚合建議:現代版本優先使用LISTAGG,僅在舊版本或需動態表名時使用自訂函數。