1

所以我试图利用LISTAGG()函数来简单地构建一个逗号分隔的列表以在基础查询中使用。列表生成工作正常,我只是为了调试目的应用了一个输出,我可以看到我的列表应该是这样的:

值:'AB','AZ','BC','CA','CT','DC','FL','FO','GA','IL','KS','MA', 'MB','ME','MN','MS','MT','NB','NC','NL','NOVA SCOTIA','NS','NT','NU',' NY','ON','ONTARIO','OR','PE','QC','QUEBEC','QUEBEC','SASKATCHEWAN','SK','TX','VT','WA' ,'YT'

当我尝试将此列表变量传递给我的查询时,只是想看看是否有任何东西会回来,什么都不会回来,但是如果我从上面(原样)复制/过去的省/州列表而不是在我的where 子句,我得到一个结果。我究竟做错了什么?

  DECLARE
     v_PROVINCE varchar2(500);
     v_results varchar2(1000);
  BEGIn
        dbms_output.enable(1000000);  

       Select '''' || LISTAGG(STATE, ''',''') WITHIN GROUP (ORDER BY STATE) || '''' PROV 
       INTO v_PROVINCE
       from (Select distinct STATE from ADDRDATA where STATE IS NOT NULL);

   DBMS_OUTPUT.PUT_LINE('VALUES: ' || v_PROVINCE);

   Select CITY
   INTO v_results
   from VWPERSONPRIMARYADDRESS
   where state in (v_Province)
   AND ROWNUM <= 1;

   DBMS_OUTPUT.PUT_LINE(v_results);


  END;
  /
4

2 回答 2

2

首先,如果可能的话,在单个语句中完成所有事情几乎总是更有效。

您的第二个查询不起作用,因为您将所有内容都返回到单个字符串中。这不是IN 语句所要求的逗号分隔列表。

不过,有一个小技巧可以解决这个问题。假设您将字符串用于两个 SELECT 语句之间的某些内容,您可以regexp_substr()尝试将字符串转换为可用的内容。

像这样的东西会起作用;

select city
  from vwpersonprimaryaddress
 where state in ( 
           select regexp_substr(v_province,'[^'',]+', 1, level) 
             from dual
          connect by regexp_substr(v_province, '[^'',]+', 1, level) is not null
                  )

该变量v_province必须更改为被引用两次,例如'''AB'',''AZ'',''BC'''为了使其工作。

这是一个工作示例

于 2012-11-06T21:38:54.527 回答
1

您尝试执行的操作将不起作用,因为IN运算符将逗号分隔的列表视为单个值。理论上,您可以将值收集到单个字符串中,然后将字符串解析为单独的值,以便您的下一个查询可以解释它。但是,这将是一个非常糟糕的主意。

一个更好的主意是使用数组将您的值列表从第一个查询传递到第二个查询:

create type nt_varchar_50 as table of varchar2(10)
/

DECLARE
     v_PROVINCE nt_varchar_50;
     v_results varchar2(1000);
     cursor cur_provinces is
        Select distinct STATE from ADDRDATA where STATE IS NOT NULL;
     i pls_integer;
BEGIN
     dbms_output.enable(1000000); 
     open cur_provinces;
     fetch cur_provinces bulk collect into v_PROVINCE;
     close cur_provinces;

     DBMS_OUTPUT.PUT('VALUES: ');
     for i in v_PROVINCE.first .. v_province.last loop
         if i <> 1 then
            DBMS_OUTPUT.PUT(', ');
         end if;              
         DBMS_OUTPUT.PUT(v_PROVINCE(i));
     end loop;
     DBMS_OUTPUT.PUT_LINE();

     Select CITY
     INTO v_results
     from VWPERSONPRIMARYADDRESS
     where state in (select * from table(v_Province))
     AND ROWNUM <= 1;

     DBMS_OUTPUT.PUT_LINE(v_results);
END;
  /

当然,即使这样也比最初使用单个 SQL 语句的效率要低得多。确实,如果您需要在两个查询之间进行某种不适合 SQL 的处理,或者可能需要多次使用第一个结果集时,您应该只使用这种技术。

于 2012-11-06T20:51:25.223 回答