简体   繁体   English

PLSQL - 在 where 子句 IN 上使用变量数组

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

I am looking to use an array of values in the WHERE IN condition.我希望在 WHERE IN 条件下使用一组值。

After research, I saw that I had to make a "CREATE TYPE", since a "TYPE" in local does not work.经过研究,我看到我必须制作一个“CREATE TYPE”,因为本地的“TYPE”不起作用。 This solution does not suit me, I do not want to make a new TYPE in Oracle, since the database is used for an ERP/PGI I do not wish to pollute with my little need.这个解决方案不适合我,我不想在 Oracle 中创建一个新的 TYPE,因为该数据库用于 ERP/PGI,我不想因为我的小需求而受到污染。

My request is the following:我的要求如下:

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));

It is the value "('14','27','50','61','76')" that I would like to set as a variable, but only in my program.这是我想设置为变量的值“('14','27','50','61','76')”,但仅限于我的程序。

Do you have any ideas other than "CREATE TYPE"?除了“CREATE TYPE”,你还有什么想法吗?

As you don't want to create your own type, use built-in one - sys.odcivarchar2list .由于您不想创建自己的类型,请使用内置类型 - sys.odcivarchar2list For example, fetch employees who are either clerks or managers:例如,获取文员或经理的员工:

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>

If you want to declare a variable whose datatype is sys.odcivarchar2list (so, you're in a PL/SQL procedure), then如果您想声明一个数据类型为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>

replace the first with clause and str with your string variable, you can do something like this:将第一个 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)) ...

You can pass in a string (such as '14,27,50,61,76' ) as a bind variable and use LIKE to compare the delimited string:您可以传入一个字符串(例如'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<>fiddle here db<> 在这里摆弄

If you wish to pass this list of codes as a plain text (not as a bind variable of type collection), then you may use json_table function to expand the list into a table and use it as a general table with a subquery inside in predicate:如果您希望将此代码列表作为纯文本(而不是作为集合类型的绑定变量)传递,那么您可以使用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 )
 | | DUMMY |虚拟 | |:---- | |:---- | | | X | × |

db<>fiddle here db<> 在这里摆弄

If you want to pass this codes as an array (collection in Oracle), then use built-in collection type sys.odcivarchar2list , but you'll need to prepare a bind variable of this type at the application side depending on the programming language (for example, here's an explanation with examples from the official docs for Python).如果您想将此代码作为数组(Oracle 中的集合)传递,则使用内置集合类型sys.odcivarchar2list ,但您需要根据编程语言在应用程序端准备此类型的绑定变量(例如, 这是 Python 官方文档中示例的解释)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM