我想做这样的事情:
sql_str := 'select ';
if (user_input = 1) then
sql_str := sql_str || 'a.col1 from tb1 a';
else
sql_str := sql_str || 'a.col1, b.col2, b.col3 from tb1 a, tb2 b';
execute sql_str
我对Oracle的程序,功能等没有多少经验,更不用说了。
我无法找到如何在Oracle中创建过程(或函数)来执行上述代码。
感谢任何帮助。谢谢。
答案 0 :(得分:1)
使用您的示例,这是动态SQL的一种方法
正如其他人所说,Stack Exchange上有很多动态sql的例子。
这篇文档非常好subject。我喜欢using
子句,它使动态sql更具可扩展性。
在实践中,动态sql做了一些事情:select ... into,一个程序调用,dml,dcl。
SCOTT@dev>declare
2 user_input number(1) :=1;
3 sql_str varchar2(1000);
4 begin
5
6 sql_str := 'select ';
7 if (user_input = 1) then
8 -- sql_str := sql_str || 'a.col1 from tb1 a';
9 sql_str := sql_str || '''1'' from dual';
10 dbms_output.put_line(sql_str);
11 else
12 -- sql_str := sql_str || 'a.col1, b.col2, b.col3 from tb1 a, tb2 b';
13 sql_str := sql_str || '''2'' from dual';
14 dbms_output.put_line(sql_str);
15 end if;
16 execute immediate sql_str;
17 end;
18 /
select '1' from dual
PL/SQL procedure successfully completed.
SCOTT@dev>declare
2 user_input number(1) :=2;
3 sql_str varchar2(1000);
4 begin
5
6 sql_str := 'select ';
7 if (user_input = 1) then
8 -- sql_str := sql_str || 'a.col1 from tb1 a';
9 sql_str := sql_str || '''1'' from dual';
10 dbms_output.put_line(sql_str);
11 else
12 -- sql_str := sql_str || 'a.col1, b.col2, b.col3 from tb1 a, tb2 b';
13 sql_str := sql_str || '''2'' from dual';
14 dbms_output.put_line(sql_str);
15 end if;
16 execute immediate sql_str;
17 end;
18 /
select '2' from dual
PL/SQL procedure successfully completed.
我的例子正如人们所评论的那样,一个简单的select
语句通常没有意义(在实践中没有人这样做)。
可以看到我的动态sql是通过查看显示共享sql区域的统计信息的v$sql
来解析的:
APPS@dev>SELECT
2 sql_id
3 FROM
4 v$sql
5 WHERE
6 1 = 1
7 AND (
8 sql_text = 'select ''1'' from dual'
9 OR
10 sql_text = 'select ''2'' from dual'
11 ) AND
12 parsing_schema_name = 'SCOTT';
SQL_ID
-------------
27q1fj58cnz0k
c9bw73fh2ay8d
正如Alex所引用的那样,文档表明没有into
子句的select语句不会被执行。它至少被解析,可以在共享的sql区域中看到,v $ sql。
这是我的into
子句的示例。
APPS@dev>DECLARE
2 user_input NUMBER(1) := 1;
3 sql_str VARCHAR2(1000);
4 v_val VARCHAR2(1);
5 BEGIN
6 sql_str := 'select ';
7 IF
8 ( user_input = 1 )
9 THEN
10 -- sql_str := sql_str || 'a.col1 from tb1 a';
11 sql_str := sql_str || '''1'' from dual';
12 ELSE
13 -- sql_str := sql_str || 'a.col1,b.col2,b.col3 from tb1 a,tb2 b';
14 sql_str := sql_str || '''2'' from dual';
15 END IF;
16
17 EXECUTE IMMEDIATE sql_str INTO
18 v_val;
19 dbms_output.put_line(sql_str || ' => ' || v_val);
20 END;
21 /
select '1' from dual => 1
PL/SQL procedure successfully completed.
答案 1 :(得分:1)
由于您没有返回任何价值,我们必须去寻找程序。虽然用例不明确。
CREATE PROCEDURE dyn_sql_query (user_input IN NUMBER)
IS
sql_str VARCHAR2 (500) := 'SELECT ';
BEGIN
IF (user_input = 1)
THEN sql_str := sql_str || 'a.col1 from tb1 a';
ELSE sql_str := sql_str || 'a.col1, b.col2, b.col3 from tb1 a, tb2 b';
END IF;
EXECUTE IMMEDIATE sql_query;
END;
这是函数(通知RETURN
)的非常基本的脚本,它接受表名并返回行数。
CREATE FUNCTION count_rows (table_name IN VARCHAR2)
RETURN PLS_INTEGER //
IS
sql_query VARCHAR2 (500) := 'SELECT COUNT(*) FROM ' || table_name;
ret_val PLS_INTEGER;
BEGIN
EXECUTE IMMEDIATE sql_query INTO ret_val;
RETURN ret_val;
END;
答案 2 :(得分:1)
我不确定它是否对您有所帮助,但您可以创建类似下面的程序
CREATE OR REPLACE PROCEDURE test_Ali (user_input IN VARCHAR2(2))
IS
sql_str VARCHAR2(1000):= 'select ';
user_input VARCHAR2(2) := '1';
BEGIN
IF user_input = '1' THEN
BEGIN
sql_str := sql_str||'a.col1 from tb1 a';
EXECUTE IMMEDIATE sql_str;
dbms_output.put_line (sql_str) ;
END;
ELSE
BEGIN
sql_str := sql_str||'a.col1, b.col2, b.col3 from tb1 a, tb2 b';
EXECUTE IMMEDIATE sql_str;
dbms_output.put_line (sql_str) ;
END;
END IF;
END;