我有一个简单的查询:
select * from countries
结果如下:
country_name ------------ Albania Andorra Antigua .....
我想在一行中返回结果,所以像这样:
Albania, Andorra, Antigua, ...
当然,我可以编写一个PL/SQL函数来完成这项工作(我已经在Oracle 10g中完成了),但是对于这个任务是否有更好的,最好是非特定于Oracle的解决方案(或者可能是内置函数) ?
我通常会用它来避免子查询中的多行,所以如果一个人有一个以上的公民身份,我不希望她/他在列表中是重复的.
我的问题是基于SQL Server 2005上的类似问题.
更新:我的功能如下:
CREATE OR REPLACE FUNCTION APPEND_FIELD (sqlstr in varchar2, sep in varchar2 ) return varchar2 is ret varchar2(4000) := ''; TYPE cur_typ IS REF CURSOR; rec cur_typ; field varchar2(4000); begin OPEN rec FOR sqlstr; LOOP FETCH rec INTO field; EXIT WHEN rec%NOTFOUND; ret := ret || field || sep; END LOOP; if length(ret) = 0 then RETURN ''; else RETURN substr(ret,1,length(ret)-length(sep)); end if; end;
JoshL.. 114
该WM_CONCAT
函数(如果包含在数据库中,Oracle 11.2之前版本)或LISTAGG
(启动Oracle 11.2)应该可以很好地完成.例如,这会在模式中获取以逗号分隔的表名列表:
select listagg(table_name, ', ') within group (order by table_name) from user_tables;
要么
select wm_concat(table_name) from user_tables;
更多细节/选项
链接到文档
该WM_CONCAT
函数(如果包含在数据库中,Oracle 11.2之前版本)或LISTAGG
(启动Oracle 11.2)应该可以很好地完成.例如,这会在模式中获取以逗号分隔的表名列表:
select listagg(table_name, ', ') within group (order by table_name) from user_tables;
要么
select wm_concat(table_name) from user_tables;
更多细节/选项
链接到文档
这是一种没有stragg或创建函数的简单方法.
create table countries ( country_name varchar2 (100)); insert into countries values ('Albania'); insert into countries values ('Andorra'); insert into countries values ('Antigua'); SELECT SUBSTR (SYS_CONNECT_BY_PATH (country_name , ','), 2) csv FROM (SELECT country_name , ROW_NUMBER () OVER (ORDER BY country_name ) rn, COUNT (*) OVER () cnt FROM countries) WHERE rn = cnt START WITH rn = 1 CONNECT BY rn = PRIOR rn + 1; CSV -------------------------- Albania,Andorra,Antigua 1 row selected.
正如其他人所提到的,如果你使用11g R2或更高版本,你现在可以使用更简单的listagg.
select listagg(country_name,', ') within group(order by country_name) csv from countries; CSV -------------------------- Albania, Andorra, Antigua 1 row selected.
对于Oracle,您可以使用LISTAGG
你也可以使用它:
SELECT RTRIM ( XMLAGG (XMLELEMENT (e, country_name || ',')).EXTRACT ('//text()'), ',') country_name FROM countries;
你可以试试这个查询.
select listagg(country_name,',') within group (order by country_name) cnt from countries;