plsql select return 值使用 dbms_sql 12c

plsql select return value using dbms_sql 12c

嗯,在 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.

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

dbms_sql.column_value(cur, 1, cnt);

From the documentation:

COLUMN_VALUE Procedure
This procedure returns the value of the cursor element for a given position in a given cursor. This procedure is used to access the data fetched by calling 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 table 相反,我看到:

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

PL/SQL procedure successfully completed.

SQL> select count(*) from employees;

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