首页 > 解决方案 > 在 Oracle 中,IN 运算符后面是否有数据类型?

问题描述

我有一个关于 Oracle PL/SQL 的问题。

在一个过程中,相同的嵌入式 SELECT 语句在查询中与 WHERE 子句一起重复使用:

...
where start_year in (
   SELECT MB_START FROM MEMBERS
)
...

嵌入在过程中 WHERE 子句中的实际 SELECT 语句更详细,并替换为“SELECT MB_START FROM MEMBERS”,以使我的问题更容易理解。这正是我问这个问题的原因:

在许多 WHERE 子句中重复相同的子查询很麻烦,使阻塞的代码难以阅读,并且是服务器资源的潜在浪费。有没有办法将嵌入式子查询返回的内容保存在变量中,例如:

DECLARE
   start_years <type_for_IN_operator>;
BEGIN
   ...
   select mb_start into start_years from members;
   ...
   WHERE start_year in (start_years)
   ...
END;
/

我努力搜索,但未能确定 Oracle 是否支持将值保存在变量中以供 IN 运算符使用。如果支持,type_for_IN_operator 的数据类型是什么?

对答案和进一步问题的回应:

谢谢大家对这个问题的回答。

我问这个问题是因为我观察到 IN 运算符接受一组不同形式的值,例如

因此我认为它们可能有一些共同点,例如我不知道的数据类型。如果有这样的数据类型,查询代码可能会更简单、更容易。

我被APC的想法所吸引,特别是它是纯sql,虚拟表是可重用的。我试过了,但遇到了问题。

该脚本最初是:

select t.col1, t.col2, ... from
(
  select ...
  from ...
  where start_year in (<that subquery>)
  union
  select ...
  from ...
  where start_year in (<that subquery>)
  union
  ...
) t
join ...
...

现在使用虚拟表并替换第一个原始子查询:

with sqf as (
    SELECT MB_START FROM MEMBERS
)
select t.col1, t.col2, ... from
(
  select ...
  from ...
  where start_year in (select * from sqf)
  union
  select ...
  from ...
  where start_year in (<that subquery>)
  union
  ...
) t
join ...
...

碰巧查询完成的速度甚至比原始代码还要快。但是,当第二个 <that subquery> 也被替换为 sqf 虚拟表时,查询将永远运行,尽管它也没有吐出任何错误。我不得不杀了它。我又试了几次,它的行为方式相同。

有什么建议吗?

标签: oracleplsql

解决方案


oracle 中的任何查询都会根据选择的列返回一个游标。是否在 IN 条件下调用它并不重要。

但是,如果您想保存子查询的结果以在多个查询中重复使用,您可以创建一个 TYPE 并在其中批量收集您的值。

CREATE TYPE MEMBER_TAB_TYPE AS TABLE OF DATE;

DECLARE 
  MB_START_TABLE MEMBER_TAB_TYPE;
BEGIN 
  SELECT MB_START BULK COLLECT INTO MB_START_TABLE FROM MEMBERS;
  ....
  WHERE START_YEAR IN (SELECT COLUMN_VALUE FROM TABLE(MB_START_TABLE));
  ....
END;

您可以在程序中任意多次使用 MB_START_TABLE,而无需实际查询 MEMBERS 表,因为“SELECT COLUMN_VALUE FROM TABLE(MB_START_TABLE)”将始终获取本地存储的值。


推荐阅读