Oracle
 sql >> база данни >  >> RDS >> Oracle

SELECT от таблица с Varying IN списък в клауза WHERE

Вашето изискване се нарича Променливи IN-списъци . Вижте Променлив IN списък със стойности в клаузата WHERE

Причина: IN ('1, 2, 3') еНЕ същото като IN (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('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);

което ще ви даде правилен изход -

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

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

Решение:

За вашето изискване можете да го постигнете по следния начин -

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, разделен със запетая, на няколко реда . Как ще го направите зависи от вас!

Работна демонстрация

Да вземем пример за стандартния EMP таблица в SCOTT схема.

Имам списък с работни места в низ и искам да преброя служителите за тези работни места:

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 списък .

Нека видим правилния начин:

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.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. CRS 11.2.0

  2. Пример за израз на Oracle FOR LOOP SELECT

  3. Как да актуализирате таблицата в oracle

  4. ORA-01111 в MRP във Physical Standby база данни

  5. PL/SQL променливите в курсорите ефективно ли са същите като параметрите за свързване?