【问题标题】:Is it possible to iterate over a list of strings and conditionally query an oracle database table based on the current value using SQL or PL/SQL?是否可以遍历字符串列表并使用 SQL 或 PL/SQL 根据当前值有条件地查询 oracle 数据库表?
【发布时间】:2021-11-20 20:36:46
【问题描述】:

是否可以使用 SQL 或 PL/SQL 根据字符串列表中的当前值进行条件查询?如果有帮助,我正在使用 Oracle 数据库?

所需功能示例(伪代码):

for stringVal in ('string1', 'string2', 'string3'):
  if (stringVal == 'string2'):
    select * from SCHEMA.TABLE where CONDITION;
  else:
    select * from OTHER_SCHEMA.OTHER_TABLE where CONDITION;

【问题讨论】:

    标签: sql database oracle plsql


    【解决方案1】:

    如果条件不依赖于输入数据并且结果集包含相同的列,那么您可以使用由 unions 组成的简单视图,并将常量作为附加列并按该列进行过滤。优化器很聪明地找出它并避免访问过滤出的对象(请参阅starts 列)。

    create view v_test as
    select
      'table_1' as src, t1.*
    from t1
    where val = 3
    
    union all
    
    select 'table_2', t2.*
    from t2
    where id < 10
    
    select /*+gather_plan_statistics*/ *
    from v_test
    where src = 'table_1'
    
    SRC |身份证 |价值 | STR :-------- | -: | --: | :--------- 表_1 | 3 | 3 | KJVK9GPV5D 表_1 | 8 | 3 | 5VQT72ICVR 表_1 | 13 | 3 | 7依雅摩AA7 表_1 | 18 | 3 | NXGVIP1CFX
    select *
    from table(dbms_xplan.display_cursor(format => 'TYPICAL ALLSTATS LAST'))
    
    |计划表输出 | | :------------------------------------------------ -------------------------------------------------- ------------------------------ | | SQL_ID bfc7qqct9vamf,子编号 0 | | -------------------------------------- | | select /*+gather_plan_statistics*/ * from v_test where src = 'table_1' | | | |计划哈希值:2711242194 | | | | -------------------------------------------------- -------------------------------------------------- ------------------------------ | | |身份证 |操作 |姓名 |开始 |电子行 |电子字节|成本 (%CPU)|电子时代 | A-行 |时间 |缓冲器 |阅读 | | | -------------------------------------------------- -------------------------------------------------- ------------------------------ | | | 0 |选择声明 | | 1 | | | 3 (100)| | 4 |00:00:00.01 | 2 | 1 | | | | 1 |查看 | V_TEST | 1 | 5 | 10185 | 3 (0)| 00:00:01 | 4 |00:00:00.01 | 2 | 1 | | | | 2 | UNION-ALL | | 1 | | | | | 4 |00:00:00.01 | 2 | 1 | | | |* 3 |表访问完全 | T1 | 1 | 4 | 68 | 3 (0)| 00:00:01 | 4 |00:00:00.01 | 2 | 1 | | | |* 4 |过滤器 | | 1 | | | | | 0 |00:00:00.01 | 0 | 0 | | | |* 5 |表访问已满| T2 | 0 | 10 | 220 | 3 (0)| 00:00:01 | 0 |00:00:00.01 | 0 | 0 | | | -------------------------------------------------- -------------------------------------------------- ------------------------------ | | | |谓词信息(由操作 id 标识):| | -------------------------------------------------- - | | | | 3 - 过滤器(“VAL”=3)| | 4 - 过滤器(NULL 不是 NULL)| | 5 - 过滤器(“ID”

    db小提琴here

    如果条件是动态的并且取决于输入数据,那么我将使用另一个答案中发布的现代SQL Macro

    【讨论】:

      【解决方案2】:

      根据您使用的版本,您可以使用 SQL 宏来执行此操作。这些从 19.6 或 19.7 开始可用 .. 简单的例子,你明白了:

      SQL> create or replace function what_shall_i_do(tab dbms_tf.table_t, col dbms_tf.columns_t)
        2                    return varchar2 SQL_Macro is
        3    stmt clob := 'select ';
        4    cnm clob;
        5  begin
        6    for i in 1 .. col.count loop
        7      cnm := col(i);
        8      stmt := stmt || cnm || ',';
        9    end loop;
       10
       11    return rtrim(stmt, ',') || ' from tab';
       12
       13  end;
       14
       15* /
      
      Function WHAT_SHALL_I_DO compiled
      
      SQL> select * from what_shall_i_do(dual, columns(dummy));
        2*
      
         DUMMY
      ________
      X
      
      SQL> select * from what_shall_i_do(sh.customers, columns(cust_id)) fetch first 5 rows only;
        2*
      
         CUST_ID
      __________
           49671
            3228
            6783
           10338
           13894
      
      SQL>
      

      【讨论】:

      • 不错的命名约定
      【解决方案3】:

      有可能吗?是的。例如:

      SQL> declare
        2    l_result number;
        3  begin
        4    for stringval in (select 'string1' col from dual union all
        5                      select 'string2'     from dual union all
        6                      select 'string3'     from dual
        7                     )
        8    loop
        9      if stringval.col = 'string2' then
       10         select max(sal)
       11           into l_result
       12           from scott.emp;
       13      else
       14         select min(deptno)
       15           into l_result
       16           from mike.dept;
       17      end if;
       18      dbms_output.put_line('Stringval.col = ' || stringval.col || '; result = ' || l_result);
       19    end loop;
       20  end;
       21  /
      Stringval.col = string1; result = 10
      Stringval.col = string2; result = 5000
      Stringval.col = string3; result = 10
      
      PL/SQL procedure successfully completed.
      
      SQL>
      

      但请注意,

      • IF 属于 PL/SQL
      • SELECT 必须有它的INTO;我的示例是一个简单的示例,仅将单个值返回到标量变量中。根据您的查询实际返回的内容,您可能无法做到这一点,但使用例如一个集合或引用光标

      【讨论】:

      • 谢谢小脚
      猜你喜欢
      • 1970-01-01
      • 2019-11-24
      • 2018-11-22
      • 1970-01-01
      • 2016-11-02
      • 2021-11-24
      • 2021-12-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多