如何在oracle中有条件地执行DDL?

时间:2014-04-03 16:36:13

标签: sql database oracle plsql

我有一个脚本可以创建很多表,索引,触发器等。我想有条件地运行所有这些DDL。我试图用'if then'包装脚本,但它不起作用

IF exists (select 1 from xxx where yyy) THEN

    create table...

    create table...

    CREATE UNIQUE INDEX ...

    CREATE TRIGGER ...

END IF;

我怎样才能实现这一目标?

1 个答案:

答案 0 :(得分:4)

其中一种方式:

begin
    for cur in (select 1 from xxx where yyy and rownum <= 1) loop
     execute immediate 'create table...';
     execute immediate 'create table...';
     execute immediate 'create unique index...';
    end loop;
end;
/

P.S。另一种方法是生成异常并继续SQL * Plus。

file example.sql:

SET ECHO OFF
SET VERIFY OFF
WHENEVER SQLERROR EXIT;

VAR x NUMBER
EXEC :x := &1
BEGIN
  FOR cur IN (SELECT 1 FROM dual WHERE 1=:x) LOOP
    RETURN;
  END LOOP;
  RAISE NO_DATA_FOUND;
END;
/

PROMPT Here we are

结果:

SQL> @example
Enter value for 1 1: 1

PL/SQL procedure completed.


PL/SQL procedure completed.

Here we are
SQL> @example
Enter value for 1: 2

PL/SQL procedure completed.

BEGIN
*
error in line 1:
ORA-01403: no data found
ORA-06512: in line 5 

当我使用值2时,块引发异常,脚本存在SQL * Plus。

P.S。还有一个回应的例子 - 希望下面的清洁问题。我只在不存在时创建表。表包含1024个分区和DEFAULT语句中的'字符。文字大小&gt; 32K。

SQL> set serveroutput on
SQL> DECLARE
  2   sql_code clob;
  3   delim varchar2(1) := '';
  4   amount int;
  5   sql_text varchar2(32767);
  6  BEGIN
  7  
  8    dbms_lob.createtemporary(sql_code,cache => true);
  9    sql_text := q'[CREATE TABLE TEST_TAB (X INT PRIMARY KEY, Y VARCHAR2(10) DEFAULT 'DEF', Z INTEGER) PARTITION BY RANGE(Z) ( ]';
 10    amount := length(sql_text);
 11    dbms_lob.writeappend(sql_code,amount,sql_text);
 12  
 13    for i in 1..1024 loop
 14        sql_text := delim||'PARTITION P_'||i||' VALUES LESS THAN ('||i||')';
 15        amount := length(sql_text);
 16        dbms_lob.writeappend(sql_code,amount,sql_text);
 17        delim := ',';
 18    end loop;
 19  
 20    dbms_lob.writeappend(sql_code,1,')');
 21  
 22    FOR cur IN (
 23      SELECT * FROM dual WHERE NOT EXISTS (
 24             SELECT * FROM user_tables WHERE table_name = 'TEST_TAB')
 25    ) LOOP
 26      EXECUTE IMMEDIATE sql_code;
 27    END LOOP;
 28  
 29    dbms_output.put_line(dbms_lob.getlength(lob_loc => sql_code));
 30  
 31  END;
 32  /
39877                                                                           

PL/SQL procedure completed.

SQL> desc test_tab
 Имя                                       Пусто?   Тип
 ----------------------------------------- -------- ----------------------------
 X                                         NOT NULL NUMBER(38)
 Y                                                  VARCHAR2(10)
 Z                                                  NUMBER(38)

SQL> select count(*) from user_tab_partitions where table_name = 'TEST_TAB';

  COUNT(*)                                                                      
----------                                                                      
      1024