oracle执行动态sql选择脚本并返回表格数据

Posted

技术标签:

【中文标题】oracle执行动态sql选择脚本并返回表格数据【英文标题】:Oracle execute dynamic sql select script and return tabular data 【发布时间】:2020-07-16 16:02:44 【问题描述】:

我正在尝试执行动态 sql select 语句并将结果返回给 C# ExecuteReader。

我可以使用以下 sql 代码在 sql server 中检索结果。

Create Table TestCustomer(ID Varchar(50), CustomerName Varchar(100));

Insert Into TestCustomer (ID, CustomerName) Values ('1', 'One');
Insert Into TestCustomer (ID, CustomerName) Values ('2', 'Two');
Insert Into TestCustomer (ID, CustomerName) Values ('3', 'Three');

DECLARE @SQLScript VARCHAR(MAX), @CustomerName VARCHAR(100);

SET @CustomerName = 'Two';
SET @SQLScript = 'select * from TestCustomer where CustomerName = '''+ @CustomerName +''' ';
EXEC(@SQLScript);

但是当我尝试使用以下 oracle sql 代码在 oracle 服务器上检索结果时,我没有看到表结果像 sql server 那样出来。

DECLARE 
SQLScript VARCHAR2(4000);
CustomerName VARCHAR2(20) := 'Two';
BEGIN
SQLScript := 'select * from TestCustomer where CustomerName = :CustomerName';
EXECUTE IMMEDIATE SQLScript USING CustomerName;
END;

动态sql脚本执行后如何返回表格结果,以便c#获取表格结果?

【问题讨论】:

听起来你的问题与 C# 无关 @Crowcoder,如果oracle可以返回结果,C#就可以了。 对,所以不应该用c#标记。 @Crowcoder,已删除。谢谢 请尝试使用游标而不是立即执行,community.oracle.com/thread/702648 【参考方案1】:

在 Oracle 中,您必须将结果返回到某个东西。例如,进入本例所示的局部变量:

示例表:

SQL> create table testcustomer as
  2    select 1 id, 'One' customername from dual union all
  3    select 2   , 'Two'              from dual;

Table created.

PL/SQL 块:

SQL> set serveroutput on
SQL> declare
  2    sqlscript      varchar2(4000);
  3    l_customername testcustomer.customername%type := 'Two';
  4    retval         testcustomer.id%type;
  5  begin
  6    sqlscript := 'select id from testcustomer ' ||
  7                 'where customername = :1';
  8    execute immediate sqlscript into retval using l_customername;
  9
 10    -- retval now contains the ID returned by that SELECT statement
 11    dbms_output.put_line('ID = ' || retval);
 12  end;
 13  /
ID = 2

PL/SQL procedure successfully completed.

SQL>

但是,如果您想真正返回该值以便可以在其他地方使用,请考虑使用函数。稍作调整,代码如下:

SQL> create or replace function f_test
  2    (par_customername in testcustomer.customername%type)
  3    return testcustomer.id%type
  4  is
  5    sqlscript      varchar2(4000);
  6    retval         testcustomer.id%type;
  7  begin
  8    sqlscript := 'select id from testcustomer ' ||
  9                 'where customername = :1';
 10    execute immediate sqlscript into retval using par_customername;
 11
 12    -- retval now contains the ID returned by that SELECT statement
 13    return retval;
 14  end;
 15  /

Function created.

SQL> select f_test('One') from dual;

F_TEST('ONE')
-------------
            1

SQL>

当然,你可以返回各种东西;我返回了一个标量值。你可以返回一个 refcursor,一个数组,...这取决于你需要什么。

看看有没有帮助。

【讨论】:

【参考方案2】:

如果您使用的是 12c 或更高版本,则可以使用 dbms_sql.return_result 来复制您可以使用 SQL Server 执行的操作:

DECLARE 
  SQLScript VARCHAR2(4000);
  CustomerName VARCHAR2(20) := 'Two';
  MyCursor SYS_REFCURSOR;
BEGIN
  SQLScript := 'select * from TestCustomer where CustomerName = :CustomerName';
  OPEN MyCursor FOR SQLScript USING CustomerName;
  DBMS_SQL.RETURN_RESULT(MyCursor);
END;
/

在the 12cR1 'what's new' section 和PL/SQL language guide 中了解更多信息。

从 Oracle Database 12c 开始,PL/SQL 存储的子程序可以使用 PL/SQL 包 DBMS_SQL 而不是 OUT REF CURSOR 参数隐式地向其客户端返回查询结果。这种技术可以轻松地将依赖于从存储的子程序中隐式返回查询结果的应用程序从第三方数据库迁移到 Oracle 数据库。


顺便说一句,使用您的代码:

SQLScript := 'select * from TestCustomer where CustomerName = :CustomerName';
EXECUTE IMMEDIATE SQLScript USING CustomerName;

Oracle 不会抱怨,但查询实际上并没有被执行; see this note.

【讨论】:

以上是关于oracle执行动态sql选择脚本并返回表格数据的主要内容,如果未能解决你的问题,请参考以下文章

构建一些动态查询选择并立即在 Oracle PL/SQL 中显示其输出

Oracle [存储过程] 执行动态拼接SQL语句并返回结果??

Oracle 动态 SQL 多行返回

oracle 存储过程执行动态SQL 返回结果给游标,外部程序获得dataset结果集。

oracle EXECUTE IMMEDIATE动态执行sql及异常信息打印

oracle EXECUTE IMMEDIATE动态执行sql及异常信息打印