plsql使用dbms_sql 12c选择返回值

时间:2016-10-20 15:22:25

标签: plsql oracle12c

在Oracle中,EXECUTE IMMEDIATE比使用dbms_sql包更简单,但交叉租户查询除外,因为12c中的dbms_sql允许容器参数。

然而,在一个小小的测试中,我什么都没得到。即,

set serveroutput on
declare
  ret    pls_integer;
  cnt    pls_integer := 0;
  cols   number := 0;
  ctx    varchar2(128) := NULL;
  cur    number;
  stmt   varchar2(100);
begin
  stmt := 'select count(*) from scott.emp';
  cur := dbms_sql.open_cursor;
  dbms_sql.parse(c => cur,
         statement => stmt,
     language_flag => dbms_sql.native,
         container => ctx);
  dbms_sql.define_column(cur, 1, cnt);
  ret := dbms_sql.execute(cur);
  dbms_output.put_line('execute = '||ret);
  ret := dbms_sql.fetch_rows(cur);
  dbms_output.put_line('  fetch = '||ret);
  dbms_output.put_line(stmt||' = '||cnt);
  dbms_sql.close_cursor(cur);
end;
/

容器为null时 - 表示当前或忽略将允许将查询发送到目标容器。然而我怀疑我错过了一些微不足道的东西,因此我的问题;提前致谢。样本输出:

SQL> show con_name

CON_NAME
------------------------------
PDB1
SQL> set echo on
SQL> @f
SQL> set serveroutput on
SQL> declare
  2    ret       pls_integer;
  3    cnt       pls_integer := 0;
  4    cols      number := 0;
  5    ctx       varchar2(128) := NULL;
  6    cur       number;
  7    stmt      varchar2(100);
  8  begin
  9    stmt := 'select count(*) from scott.emp';
 10    cur := dbms_sql.open_cursor;
 11    dbms_sql.parse(c => cur,
 12           statement => stmt,
 13       language_flag => dbms_sql.native,
 14           container => ctx);
 15    dbms_sql.define_column(cur, 1, cnt);
 16    ret := dbms_sql.execute(cur);
 17    dbms_output.put_line('execute = '||ret);
 18    ret := dbms_sql.fetch_rows(cur);
 19    dbms_output.put_line('fetch = '||ret);
 20    dbms_output.put_line(stmt||' = '||cnt);
 21    dbms_sql.close_cursor(cur);
 22  end;
 23  /
execute = 0
fetch = 1
select count(*) from scott.emp = 0

PL/SQL procedure successfully completed.

1 个答案:

答案 0 :(得分:2)

您需要从结果集中获取实际列值:

dbms_sql.column_value(cur, 1, cnt);

From the documentation

  

COLUMN_VALUE程序
  此过程返回给定游标中给定位置的cursor元素的值。此过程用于访问通过调用FETCH_ROWS获取的数据。

所以你的代码是:

set serveroutput on
declare
  ret    pls_integer;
  cnt    pls_integer := 0;
  cols   number := 0;
  ctx    varchar2(128) := NULL;
  cur    number;
  stmt   varchar2(100);
begin
  stmt := 'select count(*) from scott.emp';
  cur := dbms_sql.open_cursor;
  dbms_sql.parse(c => cur,
         statement => stmt,
     language_flag => dbms_sql.native,
         container => ctx);
  dbms_sql.define_column(cur, 1, cnt);
  ret := dbms_sql.execute(cur);
  dbms_output.put_line('execute = '||ret);
  ret := dbms_sql.fetch_rows(cur);
  dbms_output.put_line('  fetch = '||ret);
  -- get the actual value from the column into its variable
  dbms_sql.column_value(cur, 1, cnt);
  dbms_output.put_line(stmt||' = '||cnt);
  dbms_sql.close_cursor(cur);
end;
/

如果我这样做(不可否认的是11g,那么没有container论证 - 这似乎与你的实际问题无关)和hr.employees表反而是,见:

execute = 0
  fetch = 1
select count(*) from employees = 107

PL/SQL procedure successfully completed.

SQL> select count(*) from employees;

  COUNT(*)
----------
       107