如何在 oracle 中使用 sys_refcursor 创建动态 sql

Posted

技术标签:

【中文标题】如何在 oracle 中使用 sys_refcursor 创建动态 sql【英文标题】:How to create dynamic sql for with sys_refcursor in oracle 【发布时间】:2017-08-11 08:06:36 【问题描述】:

我有返回sys_refcursor的函数我给你我的代码示例。

 function myfunc( p_city           IN VARCHAR2,
p_order           IN VARCHAR2)
RETURN SYS_REFCURSOR IS
    v_result          SYS_REFCURSOR;
begin
OPEN v_result FOR WITH all_prb AS(
select * from tableA ta inner join tableB tb)


'select * from all_prb ff where (:p_city is null or (LOWER(ff.city) like ''%''||:p_city||''%'') ) order by ' || p_order || 'asc' using p_city,p_city;
return v_result;
end myfunc;

当我试图编译它时,我有ORA-00928: missing SELECT keyword,这个错误针对我有动态sql'select * from all_prb ff where ...'的行

如何修复它以及如何编写正确的动态 sql?我正在编写用于订购的动态 sql。

【问题讨论】:

你为什么使用with 子句,为什么没有连接条件? (你发布的代码得到的是 ORA-00905,而不是 ORA-00928,所以这似乎不是你实际运行的......) 我尝试立即执行 ('select * from all_prb ff where (:p_city is null or (LOWER(ff.city) like ''%''||:p_city||''%'' ) ) order by ' || p_order || 'asc' using p_city,p_city;) 也没有说我是第一次写这样的动态 sql 所以如果你知道你能给我写代码解决方案我该怎么写?跨度> 您已将光标的一部分创建为静态,部分创建为动态。它必须全部是静态或全部是动态 sql - 即您需要在动态 sql 中包含 with 子句。 Boneist 我修复了所有问题,只是当我尝试在动态 sql 中调用其他函数时,它会写入无效标识符“functionName”,当我在动态 sql 中删除此调用时,一切正常.你能帮我如何在这段代码中调用函数吗? 【参考方案1】:

我不知道你为什么要打扰with 子句,没有 CTE 会更简单;您只需要确定city 列在哪个表中:

function myfunc(p_city IN VARCHAR2,
  p_order IN VARCHAR2)
RETURN SYS_REFCURSOR IS
  v_result          SYS_REFCURSOR;
begin
  OPEN v_result FOR
    'select * from tableA ta
     inner join tableB tb on tb.some_col = ta.some_col
     where :p_city is null or LOWER(ta.city) like ''%''||:p_city||''%''
     order by ' || p_order || ' asc'
     using p_city, p_city;

  return v_result;
end myfunc;
/

我猜是A表,如果是另一个就改别名。您还需要指定两个表之间的连接条件。 (还注意到我在 asc 之前添加了一个空格以阻止将其连接到 order-by 字符串中)。

这编译没有错误;运行时我得到 ORA-00942: table or view does not exist 这是合理的。如果我创建虚拟数据:

create table tablea (some_col number, city varchar2(30));
create table tableb (some_col number);

insert into tablea values (1, 'London');
insert into tablea values (2, 'Londonderry');
insert into tablea values (3, 'East London');
insert into tablea values (4, 'New York');

insert into tableb values (1);
insert into tableb values (2);
insert into tableb values (3);
insert into tableb values (4);

然后调用它得到:

select myfunc('lond', 'city') from dual;

  SOME_COL CITY                             SOME_COL
---------- ------------------------------ ----------
         3 East London                             3
         1 London                                  1
         2 Londonderry                             2

如果您出于某种原因真的想坚持使用 CTE,那么(正如@boneist 所说)需要成为动态声明的一部分:

  OPEN v_result FOR
    'with all_prb as (
       select * from tableA ta
       inner join tableB tb on tb.some_col = ta.some_col
     )
     select * from all_prb ff
     where :p_city is null or LOWER(ff.city) like ''%''||:p_city||''%''
     order by ' || p_order || ' asc'
     using p_city, p_city;

【讨论】:

谢谢它有效。现在我有其他问题,我想在这个动态 sql 中调用其他函数,即 'select col1,col2,otherFunc(col3) from all_prb ff',在这种情况下我有 Error ORA-00904: "otherFunc": invalid identifier 。你能帮我在这种情况下如何调用函数吗? @giorgigoginashvili - 如果你有一个新问题,你应该问一个新问题。如果otherFunc 存在并且您有权执行它(如果它不是您的,则执行直接授予您而不是通过角色),那么它将正常工作。我可以大胆猜测 - 看起来您可能在一个包中定义 myfunc,那么 otherFunc 也在一个包中吗?如果是这样,您在从 SQL 调用时必须使用包名,即使在同一个包中也是如此。 yaaah 我在同一个包中都有这两个功能,我也写了包名,但我穿错了:X 抱歉,现在一切正常,非常感谢您 不,我编辑了我的旧评论,你可以再读一遍。多谢一次

以上是关于如何在 oracle 中使用 sys_refcursor 创建动态 sql的主要内容,如果未能解决你的问题,请参考以下文章

Oracle中如何在储过程中使用临时表

如何在Oracle中使用Java存储过程

如何使用 varray 在 oracle 函数中接收多个参数

如何在存储过程(Oracle)中使用 SELECT 请求?

如何通过oracle在c#中使用多个选择查询

oracle 中 sum 如何使用,