如何对照Oracle中的动态列表检查IN条件?
编辑:更改标题以符合下面的代码 我试图从Oracle表中检索一个可接受值的列表,然后对另一个执行选择,同时将一些字段与所述列表进行比较 我试图用游标(如下所示)实现这一点,但失败了如何对照Oracle中的动态列表检查IN条件?,oracle,list,plsql,cursor,Oracle,List,Plsql,Cursor,编辑:更改标题以符合下面的代码 我试图从Oracle表中检索一个可接受值的列表,然后对另一个执行选择,同时将一些字段与所述列表进行比较 我试图用游标(如下所示)实现这一点,但失败了 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_GENE
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中如何执行此操作?为什么要拉列表而不是使用半联接
SELECT *
FROM some_other_table
WHERE some_critical_field IN (SELECT my_field
FROM my_table
WHERE some_field = some_value);
我们可以使用集合存储值以满足您的目的,但它们需要声明为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企业版中,我们可以选择使用。这是一个更好的解决方案,但并不适用于所有表 因为主SELECT语句可能会重复执行。我认为,如果迭代次数太多,任何嵌套选择都会效率低下,因此我尝试缓存我的列表。这听起来不是讽刺,但听起来好像你认为你有性能优化问题,而不是你知道你有一个问题。我建议将我提供的与APC的解决方案进行基准测试,看看是否有显著差异。事实上,我知道我有一个优化问题。我现在正忙于重构其他人的代码,因为像我上面伪键入的代码那样由块组成的SP正在破坏我们的大数据集。:)说实话,为了满足我的好奇心,我真的很有兴趣对你们的两种解决方案进行基准测试,但我更愿意尝试一些新的东西来最终解决这个问题d如果提供的嵌套子查询不引用主查询中的任何内容,Oracle应确定该子查询可以执行一次,然后重新使用结果集。这应该与将C_列表作为变量/对象集合类型相同。我们都知道,乐观主义者往往会决定做最糟糕的事情。提示可能会有所帮助,或者强制执行不同的执行计划。谢谢。我明白您的意思,但是我看到您仍然需要执行SELECT语句来填充IN子句的列表。我认为与直接半连接相比,使用此连接可以显著提高性能(如下面Adam Musch提供的)?:)令人烦恼的是,如果您的最终操作是更新或删除,那么您的代码将工作得非常好-只有选择不接受批量绑定作为输入。顺便说一句,您有资源泄漏-没有关闭引用游标。为什么不是好的本地游标?