【问题标题】: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;我的示例是一个简单的示例,仅将单个值返回到标量变量中。根据您的查询实际返回的内容,您可能无法做到这一点,但使用例如一个集合或引用光标