【问题标题】:Can a table variable be used in a select statement where clause?可以在 select 语句 where 子句中使用表变量吗?
【发布时间】:2011-12-01 20:44:15
【问题描述】:

我有一个执行两步查询的存储过程。第一步是从表中收集 VARCHAR2 类型字符的列表,并将它们收集到表变量中,定义如下:

TYPE t_cids IS TABLE OF VARCHAR2(50) INDEX BY PLS_INTEGER;
v_cids t_cids;

所以基本上我有:

SELECT item BULK COLLECT INTO v_cids FROM table_one;

这在下一点之前都可以正常工作。

现在我想在同一过程中的另一个查询的 where 子句中使用该集合,如下所示:

SELECT * FROM table_two WHERE cid IN v_cids;

有没有办法做到这一点?我可以选择单个元素,但我想像使用常规表一样使用表变量。我尝试过使用嵌套选择的变体,但这似乎也不起作用。

非常感谢,

扎克

【问题讨论】:

    标签: oracle collections oracle11g


    【解决方案1】:

    对于如何实现这一目标,您有多种选择。

    如果你想使用一个集合,那么你可以使用 TABLE 函数从中选择,但是你使用的集合类型变得很重要。

    举个简单的例子,这将创建一个数据库类型,它是一个数字表:

    CREATE TYPE number_tab AS TABLE OF NUMBER
    /
    

    类型已创建。

    下一个块然后填充集合并从中执行基本选择,将其用作表并将其连接到 EMP 表(带有一些输出,以便您查看发生了什么):

    DECLARE
       -- Create a variable and initialise it
       v_num_tab number_tab := number_tab();
       --
       -- This is a collection for showing the output
       TYPE v_emp_tabtype IS TABLE OF emp%ROWTYPE
            INDEX BY PLS_INTEGER;
       v_emp_tab v_emp_tabtype;
    BEGIN
       -- Populate the number_tab collection
       v_num_tab.extend(2);
       v_num_tab(1) := 7788;
       v_num_tab(2) := 7902;
       --
       -- Show output to prove it is populated
       FOR i IN 1 .. v_num_tab.COUNT
       LOOP
          dbms_output.put_line(v_num_tab(i));
       END LOOP;
       --
       -- Perform a select using the collection as a table
       SELECT e.*
         BULK COLLECT INTO v_emp_tab
         FROM emp e
        INNER JOIN TABLE(v_num_tab) nt
           ON (e.empno = nt.column_value);
       --
       -- Display the select output
       FOR i IN 1 .. v_emp_tab.COUNT
       LOOP
          dbms_output.put_line(v_emp_tab(i).empno||' is a '||v_emp_tab(i).job);
       END LOOP;
    END;
    

    从中可以看出,数据库 TYPE 集合 (number_tab) 被视为一个表,可以这样使用。

    另一种选择是简单地加入您在示例中选择的两个表:

    SELECT tt.*
      FROM table_two tt
     INNER JOIN table_one to
        ON (to.item = tt.cid);
    

    还有其他方法可以做到这一点,但第一种可能最适合您的需求。

    希望这会有所帮助。

    【讨论】:

    • 啊。这完美地工作。我将变量转换为我的类型,然后加入它,但出现错误。更好的是直接加入表的选项......我做了很多动态 SQL 并陷入了事情的流程,完全错过了显而易见的事情。非常感谢!
    【解决方案2】:
    --Doesn't work.
    --SELECT item BULK COLLECT AS 'mySelectedItems' INTO v_cids FROM table_one;
    
    SELECT table_two.* 
    FROM table_two INNER JOIN v_cids 
    ON table_two.paramname = v_cids.mySelectedItems;
    

    除非我误解了这个问题,否则这应该只返回表变量中的结果。

    注意:我从未使用过 Oracle,但我想这种情况会是一样的。

    【讨论】:

    • 感谢您的回答。我如何知道表变量中的参数名称是什么?是否默认为选定的列名?
    • 我相信它是默认的,如你所说。我对此不是 100% 确定的。即使没有,您也可以在原始 select 语句中使用 AS 'columnname' 来显式调用它。 - 我将其编辑为答案。
    • 我在 select 语句中尝试了显式强制转换,这产生了相同的错误('无法访问非嵌套表中的行'),然后像你一样尝试添加 AS ,但这会导致语法错误。
    • 嗯.. 抱歉。我只会运行查询并返回临时表。从那里你应该能够看到默认的列名,不是吗?
    • 是的。也许我只会使用临时表而不是表变量。我实际上无法对变量进行选择并查看列名(我知道),因为我必须遍历它,通常使用索引来访问数据,这主要是我使用这些的方式。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 1970-01-01
    • 2017-05-07
    • 2013-04-13
    • 2012-04-28
    • 1970-01-01
    • 2014-08-28
    相关资源
    最近更新 更多