删除表(如果DB2 / 400 SQL中存在)

时间:2017-04-24 08:47:11

标签: sql db2 ibm-midrange db2-400

我的目标很简单 - 如果表有行,请删除它。 尽管目前有几个类似的答案,但它们都没有为我工作。

  1. DB2 Drop table if exists equivalent
  2. 建议的解决方案:

    IF EXISTS (SELECT name FROM sysibm.systables WHERE name = 'mylib.mytable') THEN
    DROP TABLE mylib.mytable;END IF;
    

    结果:

    SQL State: 42601 Vendor Code: -199 Message: [SQL0199] Keyword IF not expected.
    Valid tokens: ( CL END GET SET CALL DROP FREE HOLD LOCK OPEN WITH ALTER BEGIN
    
    1. Drop DB2 table if exists
    2. 建议的解决方案:

      --#SET TERMINATOR @
      begin
        declare statement varchar(128);
        declare continue handle for sqlstate '42710' BEGIN END;
        SET STATEMENT = 'DROP TABLE MYLIB.MYTABLE';
        EXECUTE IMMEDIATE STATEMENT;
      end @
      

      结果:

      Message: [SQL0104] Token HANDLE was not invalid. Valid tokens: HANDLER或者,如果将handle替换为handler

      Message: [SQL0199] Keyword STATEMENT not expected. Valid tokens: SQL PATH RESULT SCHEMA CURRENT CONNECTION DESCRIPTOR.
      
      1. answer关于观看次数
      2. 建议的解决方案:

        DROP TABLE MY_TABLE ONLY IF EXISTS source

        结果:

        Message: [SQL0104] Token ONLY was not invalid. Valid tokens: RESTRICT CASCADE

        所以,我想知道是否存在替代解决方案。 CL解决方案也很有趣。

4 个答案:

答案 0 :(得分:2)

我假设你可能不止一次这样做,所以程序可能是有序的。

CREATE or replace PROCEDURE   DROP_LIVE_TABLE
  (in  @table        varchar(10)   
  ,in  @library      varchar(10)
  )
BEGIN
  declare @stmt      varchar(100);
  declare @cnt       int;

  IF exists( select * from systables
               where sys_dname = @library
                 and sys_tname = @table
                 and table_type in ('P','T')
           ) THEN
    SELECT int(sum(number_rows))
      INTO @cnt
      from SYSTABLESTAT
        where sys_dname = @library
          and sys_tname = @table
      ;
    IF @cnt > 0 THEN
      set @stmt = 'DROP TABLE '||@library||'.'||@table||' CASCADE';
      execute immediate @stmt; 
    END IF;
  END IF;
  RETURN;
END;  

CASCADE关键字也会导致删除任何依赖对象,如索引,逻辑文件,视图等。

答案 1 :(得分:1)

这是这个问题的CL答案:

         PGM        PARM(&FILENAME)

         DCL        VAR(&FILENAME) TYPE(*CHAR) LEN(10)
         DCL        VAR(&NUMRECS) TYPE(*DEC) LEN(10 0)

         RTVMBRD    FILE(&FILENAME) NBRCURRCD(&NUMRECS)
         IF         COND(&NUMRECS > 0) THEN(DLTF +
                      FILE(&FILENAME))

OUT:     ENDPGM

如果物理文件具有索引或逻辑文件等依赖项,则此解决方案会出现问题。必须首先删除这些依赖项。

另一方面,@ danny117的解决方案并不适用于所有环境。例如,我无法强制它在SQuirreL客户端中工作。但它确实可以在i Navigator中使用。它也适用于RUNSQLSTM,但我无法确定如何使它与非限定表引用一起使用。如果表格不合格,RUNSQLSTM将使用DFTRDBCOL中的默认集合。 CURRENT_SCHEMA特殊寄存器不会返回DFTRDBCOL的值。

这是if表有行使用复合语句删除它的解决方案:

begin
  if( exists(
    select 1 from qsys2.systables
    where table_schema = 'MYLIB'
      and table_name = 'MYTABLE'
  )) then
    if( exists(
      select 1 from mylib.mytable
    )) then
      drop table mylib.mytable;
    end if;
  end if;
end;

我猜你想要这样做的原因,但是如果要允许创建一个新表,那么如果你是IBM i v7.2或者最好的方法可能是CREATE OR REPLACE TABLE或者大。

如果你想要做的就是确保你有一张空桌子,TRUNCATE(v7.2 +)或DELETE可能是更好的选择。

答案 2 :(得分:1)

使用原子语句存在删除表。

BEGIN ATOMIC                  
IF( EXISTS(                   
SELECT 1 FROM TABLES           
WHERE TABLE_SCHEMA = 'MYLIB'   
AND TABLE_NAME = 'MYTABLE' 
)) THEN                       
DROP TABLE MYLIB/MYTABLE;   
END IF;                       
END;                          

答案 3 :(得分:0)

试试这个:

BEGIN    
   IF EXISTS (SELECT NAME FROM QSYS2.SYSTABLES WHERE TABLE_SCHEMA = 'YOURLIBINUPPER' AND TABLE_NAME = 'YOURTABLEINUPPER') THEN           
      DROP TABLE YOURLIB.YOURTABLE;                             
   END IF;                                                        
END  ;