在PL / SQL中的where条件下,如何在使用IN子句的新查询中使用通过INTO创建的动态变量

问题描述

DECLARE
l_filter varchar2(100);

BEGIN
   SELECT filter INTO l_filter
   FROM dashboard
   WHERE id=TARGET_ID_1;

我从中得到l_filter为('016','018','011','014')。现在,我想在下面的查询中的IN子句中动态使用此l_filter值。

select a,b from grid
where filter_value in l_filter;

如何在PL / sql中执行此操作?

解决方法

可以使用正则表达式:

select g.a,g.b
from grid g
where exists (select 1
              from dashboard d.
              where d.id = TARGET_ID_1 and
                    regexp_like(d.filter_value,'^(' || replace(d.filter,'''',''),','|') || ')$')
             );

这不是特别有效,但是不需要任何PL / SQL或动态SQL。

也就是说,您可能希望将“过滤器”存储为表中的行,这样就可以将所有内容连接在一起,从而避免了复杂性。

,

使用LIKE

DECLARE
   l_filter varchar2(100);
   cur SYS_REFCURSOR;
   a GRID.A%TYPE;
   b GRID.B%TYPE;
BEGIN
   SELECT filter
   INTO   l_filter
   FROM   dashboard
   WHERE  id = TARGET_ID_1;

   OPEN cur FOR
   SELECT a,b
   FROM   grid
   WHERE  ','||SUBSTR(l_filter,2,LENGTH(l_filter)-2)||',' LIKE '%,'''||filter_value||''',%';
   
   LOOP
      FETCH cur INTO a,b;
      EXIT WHEN cur%NOTFOUND;
      DBMS_OUTPUT.PUT_LINE(a || ',' || b);
   END LOOP;
   CLOSE cur;
END;
/

db 提琴here

,

这就是我对这个问题的理解。

首先采样数据:

SQL> select * from dashboard;

        ID FILTER
---------- -----------------------
         1 '016','018','011','014'
         2 '111','222'

SQL> select * from grid;

         A          B FIL
---------- ---------- ---
       100        200 016
       101        201 011
       200        400 xxx

SQL>

返回refcursor的函数; (在此示例中)是将filter值拆分为行,以便可以将它们用作子查询(第15-18行):

SQL> create or replace function f_get (target_id_1 in dashboard.id%type)
  2    return sys_refcursor
  3  is
  4    l_filter    varchar2(100);
  5    rc          sys_refcursor;
  6  begin
  7    select filter
  8      into l_filter
  9      from dashboard
 10      where id = target_id_1;
 11
 12    open rc for
 13      select g.a,g.b
 14      from grid g
 15      where g.filter_value in (select regexp_substr(replace(l_filter,chr(39),'[^,]+',1,level)
 16                               from dual
 17                               connect by level <= regexp_count(l_filter,') + 1
 18                              );
 19
 20    return rc;
 21  end;
 22  /

Function created.

测试:

SQL> select f_get(1) from dual;

F_GET(1)
--------------------
CURSOR STATEMENT : 1

CURSOR STATEMENT : 1

         A          B
---------- ----------
       100        200
       101        201


SQL>