plsql 使用 dbms_sql 12c 选择返回值

Posted

技术标签:

【中文标题】plsql 使用 dbms_sql 12c 选择返回值【英文标题】:plsql select return value using dbms_sql 12c 【发布时间】:2016-10-20 15:22:24 【问题描述】:

在 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_output 调用、容器名称(来自 ctx)或计数结果中看到什么? 哦,我在尝试各种事情;我更新了帖子以将 define_columns 恢复为仅 1 列到 cnt 变量。我原以为是 14 岁。 【参考方案1】:

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

dbms_sql.column_value(cur, 1, cnt);

From the documentation:

COLUMN_VALUE 过程 此过程返回给定游标中给定位置的游标元素的值。此过程用于访问通过调用 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

【讨论】:

啊,原来贴的代码错了;它已经更新了。你的版本类似。最终,这将是接收语句和容器上下文的例程的起源。所以,现在是 12c,我有兴趣寻求帮助,谢谢。 @slashlos - 但据我所知,容器与计数问题无关;您修改后的代码仍然缺少column_value 子句? 您是否还期望使用它运行的实际容器来更新ctx?我看不到任何暗示应该发生的事情,it's an IN parameter... ctx 是一个未来;是的,column_value 就是我所缺少的!

以上是关于plsql 使用 dbms_sql 12c 选择返回值的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 12c PLSQL 合并错误

oracle填坑之PLSQL中文显示为问号

oracle12C安装完成后,尝试用PLSQL连接PDB数据库,发现个问题PDB有没有SID?使用服务名来连接还是用SID?

PLSQL_V2_COMPATIBILITY 兼容性

Oracle PLSQL 无效游标错误我不明白

ORA-04036怎么解决oracle12c?