SELECT from table with Varying IN list in WHERE 子句

SELECT from table with Varying IN list in WHERE clause(SELECT from table with Varying IN list in WHERE 子句)
本文介绍了SELECT from table with Varying IN list in WHERE 子句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理的项目中遇到一个问题,我不能给你实际的代码,但我已经创建了一个可执行的示例代码,如下所示

I am facing a issue in project I am working on, I can not give you actual code but I have created a executable sample code as below

这里temptemp_id是两张表

  1. temp 表包含逗号分隔的 ID 列表,即 VARCHAR2
  2. temp_id 表包含实际的 ID,即 NUMBER
  1. temp table contains comma separated list of ids which is VARCHAR2
  2. temp_id table contains actual ids which is NUMBER

我想通过从 temp 表中的逗号分隔 id 列表中获取 ids 来搜索 temp_id 表中的行

I want to search rows from temp_id table by getting ids from comma separated list of ids from temp table

//DDLs to create table
CREATE TABLE temp(ids VARCHAR2(4000));
CREATE TABLE temp_id(data_id NUMBER);

//DMLs to populate test data
INSERT INTO temp VALUES('1, 2, 3');

INSERT INTO temp_id VALUES(1);
INSERT INTO temp_id VALUES(2);
INSERT INTO temp_id VALUES(3);
INSERT INTO temp_id VALUES(4);
INSERT INTO temp_id VALUES(5);

此查询无效

SELECT * FROM temp_id WHERE data_id IN (SELECT to_number(COLUMN_VALUE) FROM XMLTABLE(SELECT ids FROM temp));

工作查询

SELECT * FROM temp_id WHERE data_id IN (SELECT to_number(COLUMN_VALUE) FROM XMLTABLE('1, 2, 3'));

以上两个查询之间的区别是我在第一个查询中使用了 temp 表中的列,在第二个查询中使用了直接引用的 varchar2 列.没有得到不工作的原因?我错过了什么吗?我认为可能存在一些数据类型不匹配,但无法弄清楚.

Here difference between above two queries is I am using column from temp table in first query and direct quoted varchar2 in second query. Not getting the reason why is not working? Is I am missing something? I think there might be some datatype mismatch but not able to figure it out.

推荐答案

您的要求称为不同的 IN 列表.参见 变化IN WHERE 子句中的值列表

Your requirement is called as Varying IN-lists. See Varying IN list of values in WHERE clause

原因: IN ('1, 2, 3') NOTIN (1, 2, 3)IN('1', '2', '3')

因此,

SELECT * FROM temp_id WHERE data_id IN(SELECT ids FROM temp);

SELECT * FROM temp_id WHERE data_id IN(SELECT ids FROM temp);

SELECT * FROM temp_id WHERE data_id IN('1, 2, 3');

SELECT * FROM temp_id WHERE data_id IN('1, 2, 3');

这会抛出一个错误 ORA-01722: invalid number -

SQL> SELECT * FROM temp_id WHERE data_id IN('1, 2, 3');
SELECT * FROM temp_id WHERE data_id IN('1, 2, 3')
                                       *
ERROR at line 1:
ORA-01722: invalid number


SQL> SELECT * FROM temp_id WHERE data_id IN(SELECT ids FROM temp);
SELECT * FROM temp_id WHERE data_id IN(SELECT ids FROM temp)
                                              *
ERROR at line 1:
ORA-01722: invalid number

不一样

SELECT * FROM temp_id WHERE data_id IN(1, 2, 3);

SELECT * FROM temp_id WHERE data_id IN(1, 2, 3);

这会给你正确的输出 -

which would give you correct output -

SQL> SELECT * FROM temp_id WHERE data_id IN(1, 2, 3);

   DATA_ID
----------
         1
         2
         3

解决方案:

对于你的要求,你可以这样实现 -

For your requirement, you can achieve it like this -

SQL> SELECT * FROM temp;

IDS
--------------------------------------------------------------
1, 2, 3

SQL> SELECT * FROM temp_id;

   DATA_ID
----------
         1
         2
         3
         4
         5

SQL> WITH data AS
  2    (SELECT to_number(trim(regexp_substr(ids, '[^,]+', 1, LEVEL))) ids
  3    FROM temp
  4      CONNECT BY instr(ids, ',', 1, LEVEL - 1) > 0
  5    )
  6  SELECT * FROM temp_id WHERE data_id IN
  7    (SELECT ids FROM data
  8    )
  9  /

   DATA_ID
----------
         1
         2
         3

或者,您可以创建自己的TABLE 函数流水线函数来实现此目的.您的目标应该是 将逗号分隔的 IN 列表拆分为多行.你怎么做取决于你!

Alternatively, you can create your own TABLE function or a Pipelined function to achieve this. Your goal should be to split the comma-separated IN list into multiple rows. How you do it is up to you!

工作演示

让我们以 SCOTT 架构中的标准 EMP 表为例.

Let's take an example of the standard EMP table in SCOTT schema.

我有一个字符串形式的工作列表,我想计算这些工作的员工数:

I have a list of jobs in a string, and I want to count the employees for those jobs:

SQL> SET serveroutput ON
SQL> DECLARE
  2    str VARCHAR2(100);
  3    cnt NUMBER;
  4  BEGIN
  5    str := q'[CLERK,SALESMAN,ANALYST]';
  6    SELECT COUNT(*) INTO cnt FROM emp WHERE JOB IN (str);
  7    dbms_output.put_line('The total count is '||cnt);
  8  END;
  9  /
The total count is 0

PL/SQL procedure successfully completed.

哦!发生了什么?标准 emp 表应该给出输出 10.原因是不同的 IN 列表.

Oh! What happened? The standard emp table should give an output 10. The reason is that the varying IN list.

让我们看看正确的方法:

Let's see the correct way:

SQL> SET serveroutput ON
SQL> DECLARE
  2    str VARCHAR2(100);
  3    cnt NUMBER;
  4  BEGIN
  5    str := q'[CLERK,SALESMAN,ANALYST]';
  6    SELECT COUNT(*)
  7    INTO cnt
  8    FROM emp
  9    WHERE job IN
 10      (SELECT trim(regexp_substr(str, '[^,]+', 1, LEVEL))
 11      FROM dual
 12        CONNECT BY instr(str, ',', 1, LEVEL - 1) > 0
 13      );
 14    dbms_output.put_line('The total count is '||cnt);
 15  END;
 16  /
The total count is 10

PL/SQL procedure successfully completed.

这篇关于SELECT from table with Varying IN list in WHERE 子句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Execute complex raw SQL query in EF6(在EF6中执行复杂的原始SQL查询)
Hibernate reactive No Vert.x context active in aws rds(AWS RDS中的休眠反应性非Vert.x上下文处于活动状态)
Bulk insert with mysql2 and NodeJs throws 500(使用mysql2和NodeJS的大容量插入抛出500)
Flask + PyMySQL giving error no attribute #39;settimeout#39;(FlASK+PyMySQL给出错误,没有属性#39;setTimeout#39;)
auto_increment column for a group of rows?(一组行的AUTO_INCREMENT列?)
Sort by ID DESC(按ID代码排序)