从动态 SQL 打开游标时出错

Posted

技术标签:

【中文标题】从动态 SQL 打开游标时出错【英文标题】:Error opening cursor from dynamic SQL 【发布时间】:2016-04-07 13:58:19 【问题描述】:

我正在使用 Oracle PL/SQL 游标。我创建了一个光标,但我无法打开它。我收到如下错误:

Error(51,13): PLS-00320: 该表达式的类型声明不完整或格式错误

打开游标语句也出现错误。

这是我的代码:

DECLARE

   uldid uldlog.uldid%type;
   flightlegid uldlog.flightlegid%type;  
   TYPE rec IS RECORD (uldid number, uldlog number);
   --CURSOR some_cursor RETURN rec;
   CURSOR distUld return rec;  
   ress rec;


BEGIN

      MainQuery1 :='select uldlog.uldid, uldlog.flightlegid 
      from uldlog
      INTO distUld
      INNER JOIN flightulds ON uldlog.uldid = flightulds.flightuldsid 
      INNER JOIN M_ULDTYP ON FLIGHTULDS.ULDTYPEID = M_ULDTYP.ULDTYPID 
      INNER JOIN FLIGHTLEG ON FLIGHTLEG.FLIGHTLEGID = FLIGHTULDS.INFLIGHTLEGID
      INNER JOIN FLIGHTS ON FLIGHTLEG.FLIGHTID = FLIGHTS.FLIGHTID
      INNER JOIN M_AIRLINE A on A.AIRLINEID = FLIGHTS.AIRLINEID
      INNER JOIN m_flighttyp on m_flighttyp.Id=FLIGHTLEG.SERVICETYPEID  
      INNER JOIN m_pax_fr on m_pax_fr.id=m_flighttyp.pax_fr_id
      where flightulds.uldtypeid IN (3,4,5,8,9)';          

      FinalQuery1 := MainQuery1 || CommonFilterCluase || ' GROUP BY uldlog.uldid, uldlog.flightlegid';
      EXECUTE IMMEDIATE FinalQuery1;          

   OPEN distUld;
   LOOP 
      FETCH distUld into ress;
      EXIT WHEN distUld%notfound;
      NumberOfUldsDistinctEntires := NumberOfUldsDistinctEntires +1;   
      IF fn_bdtimedifference(uldid,flightlegid,FlightTypeIds,CargoType,CargoPriority,UldTypes,SlaStatusCommaSeparatedNumbers) is null then
      Bd_Avg_Time := Bd_Avg_Time + 0;
      Else 
      Bd_Avg_Time := Bd_Avg_Time + fn_bdtimedifference(uldid,flightlegid,FlightTypeIds,CargoType,CargoPriority,UldTypes,SlaStatusCommaSeparatedNumbers);
    END IF;
   END LOOP;
   CLOSE distUld; 
END;

我做错了什么?

【问题讨论】:

【参考方案1】:

您的光标声明CURSOR distUld return rec 错误。看起来您正在尝试这样做:

TYPE distUld IS REF CURSOR return rec

但是you can't use a strongly-typed ref cursor with dynamic SQL。所以你不能得到回报。您还需要该类型的实例,而不是 execute immediate - 它不应该有 into 子句 - 您动态打开引用光标:

DECLARE
  ...
  TYPE distUldType IS REF CURSOR;
  distUld distUldType;
BEGIN
   MainQuery1 :='select uldlog.uldid, uldlog.flightlegid 
      from uldlog
      INNER JOIN flightulds ON uldlog.uldid = flightulds.flightuldsid 
      ...';
   FinalQuery1 := ...;

   OPEN distUld FOR FinalQuery1;
   LOOP 
      FETCH distUld into ress;
      EXIT WHEN distUld%notfound;
      NumberOfUldsDistinctEntires := NumberOfUldsDistinctEntires +1;   
      IF fn_bdtimedifference(ress.uldid, ress.flightlegid,
         ress.FlightTypeIds, ...) is null then
      ...
   END LOOP;
   CLOSE distUld;
END;

还有其他问题超出了原始错误的范围,但基本上rec 必须为您在游标查询中选择的每一列都有字段,并且游标查询必须选择您想要传递的每一列作为您的函数的参数,并且这些调用必须使用 ress 记录变量限定字段名称。因此,您的查询必须从相应的表中获取FlightTypeIds 等; rec 需要字段来保存这些列。

您还缺少MainQuery1FinalQuery1CommonFilterCluaseNumberOfUldsDistinctEntires 的声明 - 尽管您可能没有在问题中显示这些声明。根据 CommonFilterCluase 包含的内容,您可能需要在串联中使用另一个空格。您没有使用 uldidflightlegid 变量。以此类推。

【讨论】:

以上是关于从动态 SQL 打开游标时出错的主要内容,如果未能解决你的问题,请参考以下文章

ORA-01652 从游标获取时出错

连接数据库时出错:(使用类org.gjt.mm.mysql.Driver)语句(1)没有打开游标

sql server数据库中用游标进行更新

带有游标参数 (LOOP FETCH) 和 For 循环子查询的 PL/SQL 查询出错

使用动态 SQL 时出错

动态 SQL 和游标相关问题