Cursor Select 语句 where 条件根据条件而变化

Posted

技术标签:

【中文标题】Cursor Select 语句 where 条件根据条件而变化【英文标题】:Cursor Select statement Where condition changes based on condition 【发布时间】:2018-09-21 05:52:59 【问题描述】:

我在一个过程中使用游标,这里我没有使用批量收集,因为我对从游标获取的记录进行了大量计算。

在光标的 Select 语句 Where 子句根据条件更改时,我尝试使用如下代码,但它给了我错误:

错误(19,12):PLS-00103:在预期以下情况之一时遇到符号“c_recs”::=。 (@%;

 create or replace PROCEDURE        "test" 
  (fromdate_in               IN varchar2,
     todate_in               IN varchar2,
     atype_in                IN number
    )
 is

 begin
  if atype_in = 01 then  
    cursor c_recs IS SELECT cname FROM A_AUD AA WHERE AA.atime BETWEEN to_date( '' || fromdate_in || '' ,'DD/MM/RRRR')
    AND to_date('' || todate_in || '','DD/MM/RRRR') AND AA.CTYPE IN ('RAlert');
 elsif  atype_in = 02
   cursor c_auditrecs IS  SELECT cname FROM A_AUD AA WHERE AA.atime BETWEEN to_date( '' || fromdate_in || '' ,'DD/MM/RRRR')
    AND to_date('' || todate_in || '','DD/MM/RRRR') AND AA.CTYPE IN ('DAlert');
 end if;
end


begin
--more logic

 FOR rec IN c_recs LOOP
  ---calculations

 END LOOP;

END test;

我不想使用来自 net 的 SYS_REFCURSOR,我读取的游标比 ref 游标好一点。

【问题讨论】:

【参考方案1】:

更好、更有效的选择是在没有任何 CURSOR 的单个语句中执行此操作。但是,它确实取决于您想要做什么。如果您必须根据游标记录执行 dmls,最好在单个语句中执行。

如果您确实想在循环中处理某些内容,请使用与显式游标等效(有时性能更好)的隐式游标循环。

也可以使用条件逻辑而不是 IF/ELSE 来简化选择查询。

CREATE OR REPLACE PROCEDURE "test" (
     fromdate_in   IN VARCHAR2,
     todate_in     IN VARCHAR2,
     atype_in
          in NUMBER
) is begin 

for cur in (
     SELECT cname
     FROM a_aud aa
     WHERE aa.time BETWEEN TO_DATE(fromdate_in,'dd/mm/rrrr') 
     AND TO_DATE(todate_in,'dd/mm/rrrr') AND (
          (
               atype_in = '01' AND aa.ctype = 'RAlert'
          ) OR (
               atype_in = '02' AND aa.ctype = 'DAlert'
          )
     )
) loop
                         ---calculations
    do_something_with(cur.cname)
   end loop;
 end;  
 /

我还建议您将参数类型设为日期并直接从调用块传递变量,而不是在 sql/cursor 中转换它们。这将避免 TO_DATE 转换。

【讨论】:

感谢 Nayak,我使用了这个解决方案【参考方案2】:

游标声明中的CASE 解决了这个问题:

DECLARE
   CURSOR c_recs
   IS
      SELECT cname
        FROM a_aud aa
       WHERE     aa.time BETWEEN TO_DATE (fromdate_in, 'dd/mm/rrrr')
                             AND TO_DATE (todate_in, 'dd/mm/rrrr')
             AND aa.ctype =
                    CASE
                       WHEN atype_in = '01' THEN 'RAlert'
                       WHEN atype_in = '02' THEN 'DAlert'
                    END;
BEGIN
   FOR rec IN c_recs
   LOOP
      NULL;
   END LOOP;
END;

我无法评论您的引用声明。

【讨论】:

谢谢Littlefoot,回答很有用

以上是关于Cursor Select 语句 where 条件根据条件而变化的主要内容,如果未能解决你的问题,请参考以下文章

SQL语句 select from where中可否嵌入if条件语句?

SQL语句中where条件的写法

select语句的where子句中的条件

在mysql select语句中使用条件where子句

Oracle条件查询语句-where

select语句没有where条件,limit慢咋办?