用于动态查询的 Oracle 游标

Posted

技术标签:

【中文标题】用于动态查询的 Oracle 游标【英文标题】:Oracle cursor for dynamic query 【发布时间】:2021-01-14 22:54:47 【问题描述】:

我有一个 SP 尝试为动态构建查询执行游标 这是代码

procedure echeancnew(p_entity in  varchar2,
                   ref_data OUT ref_cursor)
                   as
    v_sql VARCHAR2(2000);
    v_dblink VARCHAR2(20);
    v_entity VARCHAR2(20);
    v_test1 VARCHAR2(999);
    v_test2 VARCHAR2(999);

begin
  
  SELECT e.dblink,e.descr
          into v_dblink, v_entity 
    FROM CHM_ENTITIES e
   WHERE e.abr = p_entity;

 
  v_sql := q'|
     SELECT j.ENTRY,
     j.Curr "CUR",
     j.Ttype "TYPE",
     j.third_role "ROLE",
     t.Name_i "THIRD",
     j.third "No",
     t.Country_Descr "COUNTRY",
     To_Char(j.expire, 'MONTHYYYY') "M",
     Pkg_Jou.Ent_Bal@|' || v_dblink || q'|(Entry) "AMOUNT",
     Pkg_Jou.Ent_Bal@|' || v_dblink || q'|(Entry) * j.rate "AMNT CHF",
     Sale_Trader.Trader_Descr "RESPV",
     Purch_Trader.Trader_Descr "RESPA",
     T2.Coface "Assur.",
     CASE
       WHEN Nvl(TRUNC(SYSDATE) - TRUNC(j.expire), 0) < 15 THEN 'A<15'
       WHEN Nvl(TRUNC(SYSDATE) - TRUNC(j.expire), 0) BETWEEN 15 AND 30 THEN 'B>15<30'
       WHEN Nvl(TRUNC(SYSDATE) - TRUNC(j.expire), 0) BETWEEN 30 AND 60 THEN 'C>30<60'
       WHEN Nvl(TRUNC(SYSDATE) - TRUNC(j.expire), 0) BETWEEN 60 AND 120 THEN 'D>60<120'
       ELSE 'E>120'
    END "Past Due Inv.",'|' 
    || v_entity || q'|' as Entity

FROM Jou_Jou@|' || v_dblink || q'| j
inner join Thr_v_Third@|' || v_dblink || q'| t ON j.Ttype = t.Ttype
                                AND j.Third = t.Third
inner join Thr_Third@|' || v_dblink || q'| T2 ON j.Ttype = T2.Ttype
                               AND j.Third = T2.Third
right outer join Tra_Affair@|' || v_dblink || q'| a ON j.Entry = a.Entry_Nr
right outer join Tra_Delivery@|' || v_dblink || q'| d ON a.Delivery = d.Delivery_Id
inner join Tra_Contract@|' || v_dblink || q'| Purch ON d.From_Purchase_Contract = Purch.Contract
inner join Tra_Trader@|' || v_dblink || q'| Purch_Trader ON Purch.Trader_Transact =  Purch_Trader.Trader
inner join Tra_Contract@|' || v_dblink || q'| Sale ON d.To_Sale_Contract =Sale.Contract
inner join Tra_Trader@|' || v_dblink || q'| Sale_Trader ON Sale.Trader_Transact = Sale_Trader.Trader

WHERE j.Curr IN ('USD', 'EUR', 'GBP', 'CHF')
 AND Pkg_Jou.Ent_Bal@|' || v_dblink || q'|(Entry) != 0;|';   


v_test1 := substr(v_sql, 1 , 950);
v_test2 := substr(v_sql, 951, 950);

OPEN ref_data FOR v_sql; -- HERE I GET THE ERROR
      
end echeancnew;

我得到的错误是 ORA-00911: 无效字符

当我 concat v_test1 和 v_test2 并作为选择运行它时,它可以工作 我做错了什么?

【问题讨论】:

【参考方案1】:

如果我是你,我会删除空行,但是 - 确实错的 - 是终止 V_SQL 语句的分号:

 AND Pkg_Jou.Ent_Bal@|' || v_dblink || q'|(Entry) != 0;|'; 
                                                      ^
                                                      |
                                                   remove it!

【讨论】:

以上是关于用于动态查询的 Oracle 游标的主要内容,如果未能解决你的问题,请参考以下文章

oracle sql动态查询以选择游标中的列

Oracle 游标简介

oracle游标的使用

Oracle动态游标实现动态SQL循环遍历,和静态游标的比较。

PL/SQL:clob 字符串中的动态查询。如何打开游标?

『ORACLE』 PLSQL动态游标的使用(11g)