【问题标题】:If table have 0 rows exit procedure如果表有 0 行退出程序
【发布时间】:2016-06-29 13:06:16
【问题描述】:

我在包中有一个过程,我想实现一个逻辑,如果临时表有0行,它不会将临时表插入主表,然后转到包的下一个过程。

IF (not exists(select 1 from temp)) THEN
   RETURN;
ELSE
   EXECUTE IMMEDIATE 'TRUNCATE TABLE main';
   INSERT --+APPEND 
          INTO main
          Select * from temp;
   EXECUTE IMMEDIATE 'TRUNCATE TABLE temp';
END IF;

使用此解决方案,包编译错误。

谁能给我一些建议?

【问题讨论】:

  • 请提供错误信息。您确定 main 和 temp 具有相同的列吗?

标签: sql oracle if-statement stored-procedures plsql


【解决方案1】:

你可以使用循环,没有任何变量,只是第一次迭代,像这样

FOR a in (select 1 from temp where rownum = 1) LOOP

   EXECUTE IMMEDIATE 'TRUNCATE TABLE main';
   INSERT --+APPEND 
          INTO main
          Select * from temp;
   EXECUTE IMMEDIATE 'TRUNCATE TABLE temp';

END LOOP;

【讨论】:

    【解决方案2】:

    只计算一行,然后测试结果是0还是1:

    declare
        l_row_check integer := 0;
    begin
        select count(*) into l_row_check from main
        where  rownum = 1;
    
        if l_row_check = 0 then
            execute immediate 'truncate table main';
    
            insert --+ append 
            into main
            select * from temp;
    
            execute immediate 'truncate table temp';
        end if;
    end;
    

    【讨论】:

      【解决方案3】:

      最简单的就是用一个变量来检查:

      --- suggested edit: add condition to select 1 row at most and avoid
      --  counting big table.
      select count(1) into v_count from temp where rownum <=1;
      
      IF (v_count=0) THEN
         RETURN;
      ELSE
         EXECUTE IMMEDIATE 'TRUNCATE TABLE main';
         INSERT --+APPEND 
                INTO main
                Select * from temp;
         EXECUTE IMMEDIATE 'TRUNCATE TABLE temp';
      END IF;
      

      【讨论】:

      • 如果表有一百万行怎么办?该代码将浪费大量时间和资源来获得它不需要的精确计数。为什么不使用“where rownum = 1”子句将计数限制为 1 行?此外,标准表达式是“count(*)”,而不是“count(1)”,IF 条件不需要括号,并且您的大写锁定已打开。
      • 就我个人而言,像这样使用SELECT INTO 会比较小心,如果您的表temp 已经为空,您最终会出现ORA-01403: no data found 错误。如果你有一个更大的数据库,这些可能很难找到。
      • @WilliamRobertson。来自 Tenzin 的优化建议,我们应该尝试rownum &lt;= 1?
      【解决方案4】:

      这里的一些答案使用SELECT INTO 方法,但我觉得这些有点棘手。
      例如,如果SELECT ColumnA INTO vcColumnA FROM Temp 没有任何记录,您最终将得到错误ORA-01403: no data found
      如果你有一个更大的数据库,这些可能很难找到。

      要遍历表并使用值做一些事情,我认为游标和记录更安全。

      例如:

      DECLARE
          CURSOR cTemp IS 
              SELECT  ColumnA, ColumnB 
              FROM    Temp;
      
          rTemp   cTemp%ROWTYPE;
      BEGIN
          OPEN cTemp;
          LOOP
              FETCH cTemp INTO rTemp;
              -- Exit when we read all lines in the Temp table. 
              EXIT WHEN cTemp%NOTFOUND;
      
              --Do something with every row. 
              --For example, print ColumnB. 
              DBMS_OUTPUT.PUT_LINE(rTemp.ColumnB);
          END LOOP;
          CLOSE cTemp;
      END;
      /
      

      【讨论】:

      • 好吧,如果您要使用显式游标,那么您不需要循环。只需获取一次并检查%found
      • 是的,如果您只期望后面一行,则不需要循环部分。我们可以使用打开的游标,获取然后关闭。
      猜你喜欢
      • 2017-03-20
      • 1970-01-01
      • 1970-01-01
      • 2020-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-08
      相关资源
      最近更新 更多