【问题标题】:How can I select from list of values in Oracle如何从 Oracle 中的值列表中进行选择
【发布时间】:2012-05-08 09:34:10
【问题描述】:

我指的是stackoverflow这个答案:

How can I select from list of values in SQL Server

如何在 Oracle 中完成类似的操作?

我在此页面上看到了使用 UNION 的其他答案,虽然这种方法在技术上有效,但我不想在我的情况下使用它。

所以我想保留或多或少看起来像逗号分隔的值列表的语法。

更新 关于create type table answer:

我有一张桌子:

CREATE TABLE BOOK
(   "BOOK_ID" NUMBER(38,0)
)

我使用这个脚本,但它没有向BOOK 表插入任何行:

create type number_tab is table of number;

INSERT INTO BOOK (
    BOOK_ID
)
SELECT A.NOTEBOOK_ID FROM
    (select column_value AS NOTEBOOK_ID from table (number_tab(1,2,3,4,5,6))) A
;

脚本输出:

TYPE number_tab compiled
Warning: execution completed with warning

但如果我使用这个脚本,它会在BOOK 表中插入新行:

INSERT INTO BOOK (
    BOOK_ID
)
SELECT A.NOTEBOOK_ID FROM
    (SELECT (LEVEL-1)+1 AS NOTEBOOK_ID FROM DUAL CONNECT BY LEVEL<=6) A
;

【问题讨论】:

    标签: sql oracle select oracle11g


    【解决方案1】:

    [已弃用] - 只是为操作添加, 你的第二个代码的问题似乎是你没有在那里定义你的“number_tab”类型。

    作为:

    CREATE type number_tab is table of number;
    
    SELECT a.notebook_id FROM (
    SELECT column_value AS notebook_id FROM table (number_tab(1,2,3,4,5,6) )  ) a; 
    
    
    INSERT INTO BOOK (  BOOK_ID )
    SELECT a.notebook_id FROM (
    SELECT column_value AS notebook_id FROM table (number_tab(1,2,3,4,5,6) )  ) a;
    
    DROP type number_tab ; 
    

    抱歉,我无法重现您的错误,您能否将使用的 oracle 版本和最初用于该过程的相同代码发送给我们?这可能会有所帮助。一切顺利。

    【讨论】:

      【解决方案2】:

      从Oracle 12.2开始,不需要TABLE函数,可以直接从内置集合中选择。

      SQL> select * FROM sys.odcinumberlist(5,2,6,3,78);
      
      COLUMN_VALUE
      ------------
                 5
                 2
                 6
                 3
                78
      
      SQL> select * FROM sys.odcivarchar2list('A','B','C','D');
      
      COLUMN_VALUE
      ------------
      A
      B
      C
      D
      

      【讨论】:

        【解决方案3】:

        您好,使用 XML-Table 的字符串也是可能的

        SELECT trim(COLUMN_VALUE) str FROM xmltable(('"'||REPLACE('a1, b2, a2, c1', ',', '","')||'"'));
        

        【讨论】:

          【解决方案4】:

          如果您要转换以逗号分隔的值列表:

          select column_value 
          from table(sys.dbms_debug_vc2coll('One', 'Two', 'Three', 'Four'));
          
          -- Or
          
          select column_value 
          from table(sys.dbms_debug_vc2coll(1,2,3,4));
          

          如果您希望转换逗号分隔值的字符串,那么我会推荐 Justin Cave 的正则表达式 SQL 解决方案。

          【讨论】:

          • 不错。我什至不必授予该过程的权限!
          • 在 oracle 和字符串中工作。比选择的解决方案更有用
          【解决方案5】:

          您不需要创建任何存储类型,您可以评估 Oracle 的内置集合类型。

          select distinct column_value from table(sys.odcinumberlist(1,1,2,3,3,4,4,5))
          

          【讨论】:

          • 它有效...!这就是我一直在寻找的。如果您能弄清楚为什么 Tony Andrews 的回答 (stackoverflow.com/questions/10353969/…) 给了我一个警告并且没有插入 - 请告诉我。
          • @SonicSoul 因为它们实际上都不是像我上面的回答那样用于“休闲”使用。 ODCI 代表 oracle 数据卡带接口,dbms_debug_vc2_coll 旨在与 DBMS_DEBUG 包一起使用。
          • 如果你有一个字符串列表,你可以使用 sys.odcivarchar2list('A','B','C')
          • 这就是我发现 SYS.ODCIVARCHAR2LIST 的原因,这正是我所需要的。谢谢!
          • @VasinYuriy 这不是 SYS.ODCI*LIST 类型的限制,因为它们可以容纳 32767 个项目,但是对于 SQL 函数的限制,它们的表达式列表最多可以有 999 个参数。您可以在 PL/SQL 中构造和填充超过 1000 项的列表并将其传递给 SQL 语句,它将工作db<>fiddle,您可以在 PL/SQL 的构造函数中传递超过 1000 项;你不能在一条 SQL 语句中传递超过 999 个项目。
          【解决方案6】:

          有多种方法可以获取逗号分隔的列表并将其解析为多行数据。在 SQL 中

          SQL> ed
          Wrote file afiedt.buf
          
            1  with x as (
            2    select '1,2,3,a,b,c,d' str from dual
            3  )
            4   select regexp_substr(str,'[^,]+',1,level) element
            5     from x
            6* connect by level <= length(regexp_replace(str,'[^,]+')) + 1
          SQL> /
          
          ELEMENT
          ----------------------------------------------------
          1
          2
          3
          a
          b
          c
          d
          
          7 rows selected.
          

          或者在 PL/SQL 中

          SQL> create type str_tbl is table of varchar2(100);
            2  /
          
          Type created.
          
          SQL> create or replace function parse_list( p_list in varchar2 )
            2    return str_tbl
            3    pipelined
            4  is
            5  begin
            6    for x in (select regexp_substr( p_list, '[^,]', 1, level ) element
            7                from dual
            8             connect by level <= length( regexp_replace( p_list, '[^,]+')) + 1)
            9    loop
           10      pipe row( x.element );
           11    end loop
           12    return;
           13  end;
           14
           15  /
          
          Function created.
          
          SQL> select *
            2    from table( parse_list( 'a,b,c,1,2,3,d,e,foo' ));
          
          COLUMN_VALUE
          --------------------------------------------------------------------------------
          a
          b
          c
          1
          2
          3
          d
          e
          f
          
          9 rows selected.
          

          【讨论】:

          • 根据我的经验,我一直使用相同的问题逻辑。为什么您描述的实现该结果的方法应该优先于使用集合?尤其是使用正则表达式和分层查询的评估看起来非常复杂!谢谢
          • @Justin Cave:谢谢,太棒了!
          【解决方案7】:

          你可以这样做:

          create type number_tab is table of number;
          
          select * from table (number_tab(1,2,3,4,5,6));
          

          Oracle 为该列命名为 COLUMN_VALUE,所以这也可以:

          select column_value from table (number_tab(1,2,3,4,5,6));
          

          【讨论】:

          • 它看起来应该可以工作..但我得到:TYPE number_tab compiled. Warning: execution completed with warning,并且在我使用此代码的地方(在封装INSERT 内),封装INSERT 不起作用。例如。我做INSERT INTO BOOK ( BOOK_ID ) SELECT A.NOTEBOOK_ID FROM (select column_value AS NOTEBOOK_ID from table (number_tab(1,2,3,4,5,6))) A ; - 没有插入行...我做错了什么?
          • 我不知道你做错了什么,或者哪里出了问题:我也在 11G 上,它对我有用。您在创建类型时收到的警告是什么?我没有收到任何警告。
          • 这基本上就是我想要的......! ...而你是第一个提出这个方向的人。但我不确定为什么create type number_tab is table of number; 会给我一个警告......如果你能弄清楚,请告诉我。谢谢。
          • 在 SQL Plus 中运行create type 命令,然后在收到警告后键入show errors 以查看详细信息。在 Toad、SQL Developer 等其他工具中,您可能可以使用类型对象(或类似的东西)上的“错误”选项卡找到。
          猜你喜欢
          • 2015-07-22
          • 2010-12-06
          • 2023-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-06
          • 2015-07-07
          相关资源
          最近更新 更多