【问题标题】:Using the "IN" clause with a comma delimited string from the output of a replace() function in Oracle SQL在 Oracle SQL 的 replace() 函数的输出中使用带有逗号分隔字符串的“IN”子句
【发布时间】:2011-06-08 00:53:07
【问题描述】:

我有一个逗号分隔的字符串,我想在语句的“IN”子句中使用它。 例如:100,101,102

由于 In 和 "IN" 子句我必须引用单独的字符串,因此我使用了替换函数: 例如:select ''''||replace('100,101,102',',',''', ''')||'''' from dual;

上面的查询有效,但是,当我尝试将上面的输出用作“IN”子句的输入时,它不返回任何数据。我只受 SQL 语句的限制,所以我不能使用 PL/SQL 代码。请帮忙。

select * from employee where employee_number in (
    select ''''||replace('100,101,102',',',''', ''')||'''' from dual);

以上行不通。请让我知道我缺少什么。

【问题讨论】:

  • 列表中的ID数量有限制吗?

标签: oracle


【解决方案1】:

在这种情况下,一般方法是将逗号分隔的列表解析为 Oracle 集合,并在 SQL 语句中使用该集合。 Tom Kyte 在variable IN lists 的讨论中有一个例子。

假设您从该线程创建 myTableType 类型和 in_list 函数,您应该能够做到

SELECT *
  FROM employee
 WHERE employee_number IN (
    SELECT *
      FROM TABLE( in_list( p_your_comma_separated_list ) )
    )

【讨论】:

  • 您好贾斯汀,感谢您的建议。不幸的是,我无权访问数据库来更改或创建任何内容。我只有读取权限,因此我仅限于“选择”。
【解决方案2】:

纯 SQL,但没有经过很好的测试...

select to_number(substr(postfix, 2, instr(postfix, ',' ,2)-2)) id 
  from (
       select substr(val, instr(val, ',', 1, n)) postfix 
         from (select ',101,102,103,' val from dual)
     , (
       select level n
         from dual 
      connect by level < 10) 
  where instr(val, ',', 1, n) > 0)
 where  instr(postfix, ',' ,2)> 2;

编辑:改进

select substr(postfix, 1, instr(postfix, ',' ,1)-1)
  from (
       select substr(val, instr(val, ',',1, level)+1) postfix
         from (select ',101,102,103,' val from dual)
      connect by instr(val, ',', 2, level) > 0
  );

注意:

  • 使用逗号前后修复字符串
  • 根据您的需要采用上限(示例中为 10)(改进版本中不需要)。
  • 使用 Justing Cave 提到的 in_list 表函数,这可能会更好:)

致谢:Stephane Faroult 的《重构 SQL 应用程序》一书中有类似的内容 (O'Reilly)

【讨论】:

  • 您好,马库斯,谢谢。您使用纯 sql 提供的解决方案运行良好。感谢您和贾斯汀的帮助。
【解决方案3】:

由于逗号分隔的值仅包含数字,为什么不尝试使用以下简单的方法:

INSTR(','||my_csv_list_of_values||',', ','||my_search_value||',') <> 0

看这个例子:

-- some test data
with employee as (
  select 101 as employee_number from dual
  union select 200 from dual
  union select 10 from dual
  union select 102 from dual)

-- the actual query
select * from employee
  where INSTR(','||'101,102,103,104'||',', ','||employee_number||',') <> 0;
--                 ^^^^^^^^^^^^^^^^^
--                   your CSV data

制作:

EMPLOYEE_NUMBER
101
102

【讨论】:

    【解决方案4】:

    如果您将整个选择格式化为字符串,则可以将您的方法与 REPLACE 和 IN 结合使用 - 然后将该字符串与 OPEN refcursor FOR 或 EXECUTE IMMEDIATE 一起使用。

    【讨论】:

      【解决方案5】:

      您可以使用 regexp_substr 函数 来获得预期的输出。
      例如 名称:='史密斯,艾伦,沃德,琼斯'; -- 这里的“NAMES”是预期输入的变量/结果。可以在IN子句中使用。

      SQL> select regexp_substr(NAMES,'[^,]+', 1, level) from dual 2  connect by regexp_substr(NAMES, '[^,]+', 1, level) is not null;
      
      
      REGEXP_SUBSTR('SMITH,A
      ----------------------
      SMITH
      ALLEN
      WARD
      JONES
      

      上述查询遍历逗号分隔的字符串,搜索逗号 (,),然后通过将逗号视为分隔符来拆分字符串。每当遇到分隔符时,它将字符串作为一行返回。
      这是一个参考Click Here

       SQL> select * from emp where ename in (
        2  select regexp_substr('SMITH,ALLEN,WARD,JONES','[^,]+', 1, level) from dual
        3  connect by regexp_substr('SMITH,ALLEN,WARD,JONES', '[^,]+', 1, level) is not null );
      
      
      
           EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
      ---------- ---------- --------- ---------- --------- ---------- ---------- ----------
            7369 SMITH      CLERK           7902 17-DEC-80        800                    20
            7499 ALLEN      SALESMAN        7698 20-FEB-81       1600        300         30
            7521 WARD       SALESMAN        7698 22-FEB-81       1250        500         30
            7566 JONES      MANAGER         7839 02-APR-81       2975                    20
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-06-11
        • 2013-06-04
        • 1970-01-01
        • 1970-01-01
        • 2017-03-06
        • 1970-01-01
        • 2015-02-20
        相关资源
        最近更新 更多