如何将VARECT与VARCHAR2一起使用Oracle 10g

时间:2016-05-24 20:44:20

标签: sql oracle10g collect listagg

我试图让COLLECT功能为我工作。我使用10g,因此发现LISTAGG和WM_CONCAT不起作用(标识符错误无效)。我拥有的数据例如如下。

Order  Lot
123    A23088
123    A23089
089    AABBCC
305    120848
305    CCDDYY

我需要返回的内容如下

Order   Lot
123     A23088, A23089
089     AABBCC
305     120848, CCDDYY

使用以下内容,我收到错误:TO_STRING是无效的标识符

TO_STRING ( CAST(COLLECT(DISTINCT LOT) AS varchar2(100)) ) AS LOT

使用以下内容,我收到错误:预期CHAR"数据类型不一致:预期%s得到%s"

TO_CHAR ( CAST(COLLECT(DISTINCT LOT) AS varchar2(100)) ) AS LOT

使用以下内容,我收到错误:预期NUMBER"数据类型不一致:预期%s得到%s"

COLLECT(DISTINCT WHSE_LOT)

有没有办法让这个功能适合我?

1 个答案:

答案 0 :(得分:1)

collect function创建一个嵌套表,在您的情况下是一个字符串表,然后您将其转换为特定类型 - 即定义为varchar2表的类型。你不能投射到一个字符串。

有一些众所周知的字符串聚合技术列表like this one。有一个that uses collect,但您仍然需要表类型和函数将生成的表转换为分隔的字符串。

逐字复制该示例:

CREATE OR REPLACE TYPE t_varchar2_tab AS TABLE OF VARCHAR2(4000);
/

CREATE OR REPLACE FUNCTION tab_to_string (p_varchar2_tab  IN  t_varchar2_tab,
                                          p_delimiter     IN  VARCHAR2 DEFAULT ',') RETURN VARCHAR2 IS
  l_string     VARCHAR2(32767);
BEGIN
  FOR i IN p_varchar2_tab.FIRST .. p_varchar2_tab.LAST LOOP
    IF i != p_varchar2_tab.FIRST THEN
      l_string := l_string || p_delimiter;
    END IF;
    l_string := l_string || p_varchar2_tab(i);
  END LOOP;
  RETURN l_string;
END tab_to_string;
/

然后使用该类型和功能:

SELECT tab_to_string(CAST(COLLECT(DISTINCT lot) AS t_varchar2_tab)) AS lot FROM ...

有趣的是,the 10g version of collect并不支持DISTINCT;它没有抱怨(!?),但留下重复。

您可以通过the set function传递该集合以删除重复项:

SELECT tab_to_string(SET(CAST(COLLECT(DISTINCT lot) AS t_varchar2_tab))) AS lot FROM ...

在10.2.0.5中运行快速演示:

create table table1(order_no number, lot varchar2(10));

insert into table1 values (590288, '2016538');
insert into table1 values (590288, '2016535');
insert into table1 values (590288, '6016535');
insert into table1 values (590288, '2016535');
insert into table1 values (590288, '2016538');

SELECT order_no, tab_to_string(SET(CAST(COLLECT(DISTINCT lot) AS t_varchar2_tab))) AS LOT
FROM table1 WHERE order_no = 590288 GROUP BY order_no;

  ORDER_NO LOT                                              
---------- --------------------------------------------------
    590288 2016538,2016535,6016535