如何在NOT IN子句中使用字符串作为变量?

3

我会给您两个SQL脚本的片段,但这足以说明问题。 首先,我正在声明一个变量:

FUNCTION Run
( i_PlafId  IN INTEGER
)
RETURN INTEGER
IS

l_tables_excl VARCHAR2(256) := 'TABLE_1,TABLE_2';

稍后我想在某个地方使用它,就像这样:

AND cos.table_name NOT IN l_tables_excl

以下哪一个是准确的表述:

AND cos.table_name NOT IN ('TABLE_1', 'TABLE_2')

由于运行此Oracle软件包需要大约2天的时间,因此无法进行实验。

提前感谢!


2
可能是Oracle BIND变量中多个值的声明的重复问题。 - sstan
2
我认为你可以在这里找到答案 - https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::p11_question_id:210612357425 - Tatiana
建议的重复问题涉及通过绑定变量获取列表,在这种情况下,它是 PL/SQL 内部的静态列表,这使得用户定义类型更实用。 - Allan
3个回答

3

处理这样的值列表的最佳方法是使用数组:

create or replace type t_table_list as table of varchar2(50);

FUNCTION Run
( i_PlafId  IN INTEGER
)
RETURN INTEGER
IS

l_tables_excl t_table_list := t_table_list('TABLE_1','TABLE_2');
...
AND cos.table_name NOT IN (select * from table(l_tables_excl))

请注意,类型必须作为数据库对象创建,而不是在包中声明。


看起来很不错,但我收到了“Error(240,34): PLS-00642: SQL语句中不允许使用本地集合类型”的错误提示... - hc0re
类型必须被创建为数据库对象,才能在SQL中使用。这意味着它必须有自己的create or replace,而不仅仅是在PL/SQL中声明。如果您可以在ALL_TYPES中看到该类型,则表示已经以正确的方式创建。 - Allan

0

选项A - 使用LIKE

您可以使用LIKE来查看表名是否在字符串中。这是否有效取决于您的表名有多相似。

/* Returns true if table name isn't a substring of l_tables.excl */
AND l_tables_excl NOT LIKE '%' || cos.table_name || '%'

选项B - 字符串拆分成表格

或者你可以将字符串拆分成一个表格,这样你就可以使用NOT IN。这有点困难,所以我会给你一些参考:

测试注意事项: 如果运行您的包需要两天时间,那么您可能需要找到一种只完成部分工作的方法。比如说,如果它处理了1000行,则添加一个变量告诉它只处理100行,这样它就能完成了。您真的需要能够进行测试,两天太长了。


0

您可以使用REGEXP_LIKE函数来模拟in子句:

WHERE NOT REGEXP_LIKE(l_tables_excl, '(^|,)'||cos.table_name||'(,|$)')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接