如何在 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的主要内容,如果未能解决你的问题,请参考以下文章