【问题标题】:How to execute DDLs conditionally in oracle?如何在 oracle 中有条件地执行 DDL?
【发布时间】:2014-04-03 16:36:13
【问题描述】:

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

IF exists (select 1 from xxx where yyy) THEN

    create table...

    create table...

    CREATE UNIQUE INDEX ...

    CREATE TRIGGER ...

END IF;

我怎样才能做到这一点?

【问题讨论】:

    标签: sql database oracle plsql


    【解决方案1】:

    其中一种方式:

    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;
    /
    

    附:另一种方法是生成异常并在 SQL*Plus 中继续。

    文件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。

    附:再举一个例子——希望这能解决下面的问题。我仅在表不存在时创建表。表在 DEFAULT 语句中包含 1024 个分区和 ' 字符。文字大小 > 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                                       
    

    【讨论】:

    • 但这意味着我必须手动转义 ddls 中的所有撇号,以便为其创建/查找一些工具
    • 您可以对字符值使用 q[''] Oracle 语法来避免手动操作。
    • @DmitryNikiforov,带括号的替代引用语法是q'[]'
    • 您能否提供更多详细信息或指向此q['']q'[]' 的链接?
    猜你喜欢
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 2020-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多