Oracle中的动态选择
我想这样做:Oracle中的动态选择,oracle,plsql,dynamic-sql,Oracle,Plsql,Dynamic Sql,我想这样做: 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中创建过程或函数
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中创建过程或函数来执行上述代码
感谢您的帮助。谢谢。使用您的示例,这里有一种实现动态SQL的方法
正如其他人所指出的,在堆栈交换上有许多动态sql的例子
这方面的文档非常好。我喜欢using子句,它使动态sql更具可扩展性
实际上,动态sql做了一些事情:选择。。。进入,程序调用,dml,dcl
在我的例子中,正如人们所评论的,一个简单的select语句通常没有意义,实际上没有人这样做
您可以通过查看v$sql来解析我的动态sql,该v$sql显示了共享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.
由于您没有返回任何值,因此我们必须执行程序。尽管用例并不清楚
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;
下面是函数notice 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;
我不确定它是否对您有帮助,但您可以创建一个如下所示的过程
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;
阅读EXECUTE IMMEDIATE。有很多问题标记为[oracle]+[dynamic sql]。也许如果你检查了几个答案,你会找到你需要的线索。我读了一些其他的问题,但仍然不能解决我的问题。不过,我会再试一次。我很难找到如何创建过程或函数-请参阅Oracle官方文档,它非常好:您实际上想实现什么-您想对查询结果做什么?如果您确实需要一个过程/函数,那么它将被调用,以及它将对结果产生什么影响?在您的示例中。但是OP没有说他们想对结果做什么…@Alex Poole是的,我同意选择声明本身没有意义。我认为这是一个选择的示范。。。这样会更好。我阅读了链接,注意到select语句不应该执行。奇怪的是,该语句随后会出现在v$sql中。@PatrickBacon不需要首先对sql进行分析和求值,以确定它不需要执行吗?这不是它出现在v$sql中的原因吗?如果重复执行,Oracle可以查看V$SQL并知道不需要执行。@Brian Leach听起来很合理。每次运行块时,执行计数实际上都会增加;但请注意,获取计数不是。使用文档中所示的示例,您可以看到序列递增之类的副作用不会发生。不管怎么说,提到它只是因为这里有一些问题,人们对结果哪里都没有结果感到困惑!。该函数与我需要的非常接近,但是我需要多个列,比如一个常规查询,而不是返回一个值count。这可能吗?是的,您可以随意更改SQL查询。在这种情况下,您需要收集到记录类型,例如ret_val[schema]。tablename%ROWCOUNT,它将反映结果集行。我搜索了更多。有了你的答案和我找到的其他信息,我得到了我想要的,所以我接受你的答案。感谢您的帮助,也感谢其他用户。
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;