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;