如何针对Oracle中的动态列表检查IN条件?

时间:2010-08-11 19:22:45

标签: oracle list plsql cursor

编辑:更改标题以适合下面的代码。

我正在尝试从Oracle表中检索可接受值的列表,然后在将某些字段与所述列表进行比较时对另一个执行SELECT。

我试图用游标(如下)来做这件事,但这失败了。

DECLARE
    TYPE gcur IS REF CURSOR;
    TYPE list_record IS TABLE OF my_table.my_field%TYPE;
    c_GENERIC gcur;
    c_LIST list_record;
BEGIN
    OPEN c_GENERIC FOR
    SELECT my_field FROM my_table
    WHERE some_field = some_value;

    FETCH c_GENERIC BULK COLLECT INTO c_LIST;

    -- try to check against list
    SELECT * FROM some_other_table
    WHERE some_critical_field IN c_LIST;

END

基本上,我要做的是将可接受的值列表缓存到变量中,因为我稍后会反复检查它。

如何在Oracle中执行此操作?

2 个答案:

答案 0 :(得分:4)

我们可以使用集合来存储值以满足您的需要,但它们需要声明为SQL类型:

create type list_record is table of varchar2(128)
/

这是因为我们不能在SQL语句中使用PL / SQL类型。这意味着我们无法使用%TYPE%ROWTYPE,因为它们是PL / SQL关键字。

您的程序将如下所示:

DECLARE
    c_LIST list_record;
BEGIN

    SELECT my_field 
    BULK COLLECT INTO c_LIST 
    FROM my_table
    WHERE some_field = some_value;

    -- try to check against list
    SELECT * FROM some_other_table
    WHERE some_critical_field IN ( select * from table (c_LIST);

END;    

  

“我看到你仍然需要表演   用于填充列表的SELECT语句   对于IN子句。“

如果值在表中,则没有其他方法可以将它们变为变量:)

  

“我在想,有一个   使用的显着性能增益   这是直接的半连接“

不一定。如果您只使用一次值,那么子查询肯定是更好的方法。但是,由于您希望在多个离散查询中使用相同的值,因此填充集合是更有效的方法。

在11g企业版中,我们可以选择使用result set caching。这是一个更好的解决方案,但不适合所有表。

答案 1 :(得分:1)

为什么要拉出列表而不是使用半连接?

SELECT * 
  FROM some_other_table 
 WHERE some_critical_field IN (SELECT my_field 
                                FROM my_table
                               WHERE some_field = some_value);