簡體   English   中英

PLSQL - 在 where 子句 IN 上使用變量數組

[英]PLSQL - Use variable array on where clause IN

我希望在 WHERE IN 條件下使用一組值。

經過研究,我看到我必須制作一個“CREATE TYPE”,因為本地的“TYPE”不起作用。 這個解決方案不適合我,我不想在 Oracle 中創建一個新的 TYPE,因為該數據庫用於 ERP/PGI,我不想因為我的小需求而受到污染。

我的要求如下:

DELETE vip_routage
 WHERE vip_tel_ext = w_array_tel(i)
   AND ((w_cp NOT IN ('14', '27', '50', '61', '76') 
   AND SUBSTR(VIP_CODE_POSTAL, 1, 2) IN ('14', '27', '50', '61', '76')) 
    OR (w_cp IN ('14', '27', '50', '61', '76') 
   AND SUBSTR(VIP_CODE_POSTAL, 1, 2) IN ('14', '27', '50', '61', '76') 
   AND TO_NUMBER(vip_dest1) < w_tri_ordre) 
    OR (w_cp NOT IN ('14', '27', '50', '61', '76') 
   AND SUBSTR(VIP_CODE_POSTAL, 1, 2) NOT IN ('14', '27', '50', '61', '76') 
   AND TO_NUMBER(vip_dest1) < w_tri_ordre));

這是我想設置為變量的值“('14','27','50','61','76')”,但僅限於我的程序。

除了“CREATE TYPE”,你還有什么想法嗎?

由於您不想創建自己的類型,請使用內置類型 - sys.odcivarchar2list 例如,獲取文員或經理的員工:

SQL> select deptno, empno, ename, job, sal
  2  from emp
  3  where job in (select *
  4                from table(sys.odcivarchar2list('CLERK', 'MANAGER'))
  5               );

    DEPTNO      EMPNO ENAME      JOB              SAL
---------- ---------- ---------- --------- ----------
        10       7934 MILLER     CLERK           1300
        30       7900 JAMES      CLERK            950
        20       7876 ADAMS      CLERK           1100
        20       7369 SMITH      CLERK            800
        10       7782 CLARK      MANAGER         2450
        30       7698 BLAKE      MANAGER         2850
        20       7566 JONES      MANAGER         2975

7 rows selected.

SQL>

如果您想聲明一個數據類型為sys.odcivarchar2list的變量(因此,您在 PL/SQL 過程中),那么

SQL> declare
  2    l_job sys.odcivarchar2list := sys.odcivarchar2list('CLERK', 'MANAGER');
  3    l_cnt number;
  4  begin
  5    select count(*)
  6      into l_cnt
  7      from emp
  8      where job in (select * from table(l_job));
  9
 10    dbms_output.put_line('Found ' || l_cnt || ' employees');
 11  end;
 12  /
Found 7 employees

PL/SQL procedure successfully completed.

SQL>

將第一個 with 子句和 str 替換為您的字符串變量,您可以執行以下操作:

with rws as (
  select '''14'',''27'',''50'',''61'',''76''' str from dual
),
item_list as (
  select regexp_substr (
           str,
           '[^,]+',
           1,
           level
         ) value
  from   rws
  connect by level <= 
    length ( str ) - length ( replace ( str, ',' ) ) + 1
)
delete from VIP_ROUTAGE
where vip_TEL_EXT = w_array_tel(i)
AND (
 (w_cp NOT IN  (select value from item_list)) ...

您可以傳入一個字符串(例如'14,27,50,61,76' )作為綁定變量並使用LIKE來比較分隔的字符串:

DELETE FROM VIP_ROUTAGE
WHERE vip_TEL_EXT = w_array_tel(i)
AND (    ',' || :your_list || ',' NOT LIKE '%,' || w_cp || ',%'
    AND (  ',' || :your_list || ',' LIKE '%,' || SUBSTR(VIP_CODE_POSTAL,1,2) || '%,'
        OR to_number(vip_dest1) < w_tri_ordre))
OR  (    ',' || :your_list || ',' LIKE '%,' || w_cp || ',%'
    AND  ',' || :your_list || ',' LIKE '%,' || SUBSTR(VIP_CODE_POSTAL,1,2) || ',%'
    AND  to_number(vip_dest1) < w_tri_ordre)

db<> 在這里擺弄

如果您希望將此代碼列表作為純文本(而不是作為集合類型的綁定變量)傳遞,那么您可以使用json_table function 將列表擴展為一個表,並將其用作in謂詞中帶有子查詢的通用表:

 with function f /*Just to emulate bind variable*/ return varchar2 as begin return q'('X','Y','Z')'; end; lkp as ( select * from json_table( '[' || /* Your string goes here instead of invocation f() */ f() || ']', '$[*]' columns ( col varchar2(100) path '$' ) ) ) select * from dual where dummy in ( /*Filter by list*/ select * from lkp )
  | 虛擬 |  |:---- |  |  × |

db<> 在這里擺弄

如果您想將此代碼作為數組(Oracle 中的集合)傳遞,則使用內置集合類型sys.odcivarchar2list ,但您需要根據編程語言在應用程序端准備此類型的綁定變量(例如, 這是 Python 官方文檔中示例的解釋)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM