所以我试图利用 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', '纽约', 'ON', '安大略', '或', 'PE', 'QC', '魁北克', '魁北克',“萨斯喀彻温省, 'SK', 'TX', 'VT', 'WA', 'YT'
当我尝试将此列表变量传递给我的查询但是只是为了查看是否会有任何回复,没有任何回复,但是如果我从上面复制/通过省/州列表(按原样)而不是使用“v_Province” “在我的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;
/
答案 0 :(得分: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'''
才能生效。
答案 1 :(得分: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的查询之间进行某种处理,或者可能需要多次使用第一个结果集,那么您应该只使用这种技术。