如何通过在 Oracle 中配对字符串来创建动态 sql
How to create dynamic sql by Pairing string in Oracle
我需要什么
- 我需要根据接收到的参数程序创建动态 sql。
Type :[A,B,C]
Code : [1,2,3]
动态sql
AND ( (in_type = 'A' and in_code = '1' )
OR (in_type = 'B' and in_code = '2')
OR (in_type = 'C' and in_code = '3')
)
我试过的解决方案
从逗号分隔的字符串
CREATE OR REPLACE TYPE t_my_list AS TABLE OF VARCHAR2(100);
CREATE OR REPLACE
FUNCTION comma_to_table(p_list IN VARCHAR2)
RETURN t_my_list
AS
l_string VARCHAR2(32767) := p_list || ',';
l_comma_index PLS_INTEGER;
l_index PLS_INTEGER := 1;
l_tab t_my_list := t_my_list();
BEGIN
LOOP
l_comma_index := INSTR(l_string, ',', l_index);
EXIT
WHEN l_comma_index = 0;
l_tab.EXTEND;
l_tab(l_tab.COUNT) := TRIM(SUBSTR(l_string,l_index,l_comma_index - l_index));
l_index := l_comma_index + 1;
END LOOP;
RETURN l_tab;
END comma_to_table;
/
FOR x IN (select * from (table(comma_to_table(in_type)) ) )
LOOP
dbms_output.put_line(x.COLUMN_VALUE);
FOR y IN (select * from (table(comma_to_table(in_code )) ) )
LOOP
dbms_output.put_line(y.COLUMN_VALUE);
IF x.COLUMN_VALUE = 'A' THEN
l_where := l_where||' AND UPPER(column_name) IN (' || upper(in_code) || ')';
END IF;
END LOOP;
END LOOP;
您可以定义单个对象集合,然后进行额外处理:
CREATE OR REPLACE TYPE t_my_item as object(
name varchar2(1),
code number
);
/
CREATE OR REPLACE TYPE t_my_list AS TABLE OF t_my_item;
declare
l_my_list t_my_list;
begin
select cast(multiset(
select t1.val, t2.val from (
select regexp_substr('A,B,C','[^,]+', 1, level ) val , level lvl
from dual
connect by regexp_substr('A,B,C', '[^,]+', 1, level) is not null) t1,
(select regexp_substr('1,2,3','[^,]+', 1, level) val , level lvl
from dual
connect by regexp_substr('1,2,3', '[^,]+', 1, level) is not null) t2
where t1.lvl = t2.lvl) as t_my_list) into l_my_list from dual;
end;
/
这是一个 select stmt:
select ' AND ( '||LISTAGG(
stmt,
' or '
) WITHIN GROUP(
ORDER BY lvl) || ' )'
from (
select t1.lvl, '(in_type = ''' || t1.val||''' and in_code = ''' || t2.val || ''' )' stmt
from (
select regexp_substr('A,B,C','[^,]+', 1, level ) val , level lvl
from dual
connect by regexp_substr('A,B,C', '[^,]+', 1, level) is not null) t1,
(select regexp_substr('1,2,3','[^,]+', 1, level) val , level lvl
from dual
connect by regexp_substr('1,2,3', '[^,]+', 1, level) is not null) t2
where t1.lvl = t2.lvl);
只需将上面的内容复制粘贴到您的方法中即可:
create or replace FUNCTION comma_to_table(p_type IN VARCHAR2, p_code IN VARCHAR2)
RETURN t_my_list
AS
l_my_list t_my_list;
begin
select cast(multiset(
select t1.val, t2.val from (
select regexp_substr(p_type,'[^,]+', 1, level ) val , level lvl
from dual
connect by regexp_substr(p_type, '[^,]+', 1, level) is not null) t1,
(select regexp_substr(p_code,'[^,]+', 1, level) val , level lvl
from dual
connect by regexp_substr(p_code, '[^,]+', 1, level) is not null) t2
where t1.lvl = t2.lvl) as t_my_list) into l_my_list from dual;
return l_my_list;
end;
/
select comma_to_table(p_type => 'A,B,C', p_code => '1,2,3') from dual;
我需要什么
- 我需要根据接收到的参数程序创建动态 sql。
Type :[A,B,C]
Code : [1,2,3]
动态sql
AND ( (in_type = 'A' and in_code = '1' )
OR (in_type = 'B' and in_code = '2')
OR (in_type = 'C' and in_code = '3')
)
我试过的解决方案
从逗号分隔的字符串
CREATE OR REPLACE TYPE t_my_list AS TABLE OF VARCHAR2(100); CREATE OR REPLACE FUNCTION comma_to_table(p_list IN VARCHAR2) RETURN t_my_list AS l_string VARCHAR2(32767) := p_list || ','; l_comma_index PLS_INTEGER; l_index PLS_INTEGER := 1; l_tab t_my_list := t_my_list(); BEGIN LOOP l_comma_index := INSTR(l_string, ',', l_index); EXIT WHEN l_comma_index = 0; l_tab.EXTEND; l_tab(l_tab.COUNT) := TRIM(SUBSTR(l_string,l_index,l_comma_index - l_index)); l_index := l_comma_index + 1; END LOOP; RETURN l_tab; END comma_to_table;
/
FOR x IN (select * from (table(comma_to_table(in_type)) ) )
LOOP
dbms_output.put_line(x.COLUMN_VALUE);
FOR y IN (select * from (table(comma_to_table(in_code )) ) )
LOOP
dbms_output.put_line(y.COLUMN_VALUE);
IF x.COLUMN_VALUE = 'A' THEN
l_where := l_where||' AND UPPER(column_name) IN (' || upper(in_code) || ')';
END IF;
END LOOP;
END LOOP;
您可以定义单个对象集合,然后进行额外处理:
CREATE OR REPLACE TYPE t_my_item as object(
name varchar2(1),
code number
);
/
CREATE OR REPLACE TYPE t_my_list AS TABLE OF t_my_item;
declare
l_my_list t_my_list;
begin
select cast(multiset(
select t1.val, t2.val from (
select regexp_substr('A,B,C','[^,]+', 1, level ) val , level lvl
from dual
connect by regexp_substr('A,B,C', '[^,]+', 1, level) is not null) t1,
(select regexp_substr('1,2,3','[^,]+', 1, level) val , level lvl
from dual
connect by regexp_substr('1,2,3', '[^,]+', 1, level) is not null) t2
where t1.lvl = t2.lvl) as t_my_list) into l_my_list from dual;
end;
/
这是一个 select stmt:
select ' AND ( '||LISTAGG(
stmt,
' or '
) WITHIN GROUP(
ORDER BY lvl) || ' )'
from (
select t1.lvl, '(in_type = ''' || t1.val||''' and in_code = ''' || t2.val || ''' )' stmt
from (
select regexp_substr('A,B,C','[^,]+', 1, level ) val , level lvl
from dual
connect by regexp_substr('A,B,C', '[^,]+', 1, level) is not null) t1,
(select regexp_substr('1,2,3','[^,]+', 1, level) val , level lvl
from dual
connect by regexp_substr('1,2,3', '[^,]+', 1, level) is not null) t2
where t1.lvl = t2.lvl);
只需将上面的内容复制粘贴到您的方法中即可:
create or replace FUNCTION comma_to_table(p_type IN VARCHAR2, p_code IN VARCHAR2)
RETURN t_my_list
AS
l_my_list t_my_list;
begin
select cast(multiset(
select t1.val, t2.val from (
select regexp_substr(p_type,'[^,]+', 1, level ) val , level lvl
from dual
connect by regexp_substr(p_type, '[^,]+', 1, level) is not null) t1,
(select regexp_substr(p_code,'[^,]+', 1, level) val , level lvl
from dual
connect by regexp_substr(p_code, '[^,]+', 1, level) is not null) t2
where t1.lvl = t2.lvl) as t_my_list) into l_my_list from dual;
return l_my_list;
end;
/
select comma_to_table(p_type => 'A,B,C', p_code => '1,2,3') from dual;