在PL / SQL中,您可以使用连接指定IN运算符的值:
v_sql := 'select field1
from table1
where field2 in (' || v_list || ')';
是否可以使用变量进行相同的操作?
v_sql := 'select field1
from table1
where field2 in (:v_list)';
若然,怎么样?
编辑:参考Marcin的答案,如何从结果表中选择?
declare
cursor c_get_csv_as_tables is
select in_list(food_list) food_list
from emp_food
where emp_type = 'PERM';
cursor c_get_food_list (v_food_table varchar2Table)is
select *
from v_food_table;
begin
for i in c_get_csv_as_tables loop
for j in c_get_food_list(i.food_list) loop
dbms_output.put_line(j.element);
end loop;
end loop;
end;
我收到以下错误:
ORA-06550: line 10, column 6:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 9, column 1:
PL/SQL: SQL Statement ignored
ORA-06550: line 15, column 34:
PLS-00364: loop index variable 'J' use is invalid
ORA-06550: line 15, column 13:
PL/SQL: Statement ignored
答案 0 :(得分:8)
就像@Sathya链接一样,你可以绑定varray(我拿了@Codo的例子):
CREATE OR REPLACE TYPE str_tab_type IS VARRAY(10) OF VARCHAR2(200);
/
DECLARE
l_str_tab str_tab_type;
l_count NUMBER;
v_sql varchar2(3000);
BEGIN
l_str_tab := str_tab_type();
l_str_tab.extend(2);
l_str_tab(1) := 'TABLE';
l_str_tab(2) := 'INDEX';
v_sql := 'SELECT COUNT(*) FROM all_objects WHERE object_type IN (SELECT COLUMN_VALUE FROM TABLE(:v_list))';
execute immediate v_sql into l_count using l_str_tab;
dbms_output.put_line(l_count);
END;
/
更新:第一个命令可以替换为:
CREATE OR REPLACE TYPE str_tab_type IS TABLE OF VARCHAR2(200);
/
然后致电:
l_str_tab.extend(1);
何时添加值
答案 1 :(得分:2)
不幸的是,您不能绑定这样的列表,但是您可以使用表函数。阅读this
以下是基于您的代码的使用示例:
declare
cursor c_get_csv_as_tables is
select in_list(food_list) food_list
from emp_food
where emp_type = 'PERM';
cursor c_get_food_list (v_food_table varchar2Table)is
select column_value food
from TABLE(v_food_table);
begin
for i in c_get_csv_as_tables loop
for j in c_get_food_list(i.food_list) loop
dbms_output.put_line(j.food);
end loop;
end loop;
end;
我在这里使用column_value伪列
答案 2 :(得分:2)
绑定变量可以在Oracle SQL查询中使用" in"条款。
以10克为单位;我不了解其他版本。
绑定变量的varchar最多为4000个字符。
示例:绑定包含以逗号分隔的值列表的变量,例如
:bindvar = 1,2,3,4,5
select * from mytable
where myfield in
(
SELECT regexp_substr(:bindvar,'[^,]+', 1, level) items
FROM dual
CONNECT BY regexp_substr(:bindvar, '[^,]+', 1, level) is not null
);
答案 3 :(得分:1)
根据@ Marcin的回答,你不能这样做,但是,有一点可以补充,因为你的查询应该实际工作,即运行。
简单地说,您不能对表或列使用绑定变量。不仅如此,绑定变量它们被假定为一个字符,所以如果你想要一个数字,你必须使用to_number(:b1)
等。
这是您的查询失败的地方。当您传入字符串时,Oracle假定您的整个列表都是单个字符串。因此,您正在有效地运行:
select field1
from table1
where field2 = v_list
没有理由不能以不同的方式做到这一点。我将假设您正在动态创建v_list
,这意味着您需要做的就是以不同方式创建此列表。一系列or
条件据称是:-),与使用in
没有区别。
据称,我的意思是永远不要依赖未经测试的东西。虽然Tom确实在链接中说可能存在性能限制,但不能保证它不会比使用in
开始更快。最好的办法是在你的查询和他的跟踪上运行跟踪,看看它有什么区别,如果有的话。
SQL> set serveroutput on
SQL>
SQL> declare
2
3 l_string varchar2(32767);
4 l_count number;
5
6 begin
7
8 for xx in ( select rownum as rnum, a.*
9 from user_tables a
10 where rownum < 20 ) loop
11
12 if xx.rnum = 1 then
13 l_string := 'table_name = ''' || xx.table_name || '''';
14 else
15 l_string := l_string || ' or table_name = ''' || xx.table_name || '
''';
16 end if;
17
18 end loop;
19
20 execute immediate 'select count(*)
21 from user_tables
22 where ' || l_string
23 into l_count
24 ;
25
26 dbms_output.put_line('count is ' || l_count);
27
28 end;
29 /
count is 19
PL/SQL procedure successfully completed.