PROCEDURE Etl_ADDR IS
      V_CNT_AG   NUMBER(10);
  BEGIN
       INSERT INTO 日志表1;
       COMMIT;   EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM 地址表1 WHERE ROWNUM<10' INTO V_CNT_AG;
  IF V_CNT_AG>0 THEN
          --备份
          EXECUTE IMMEDIATE 'TRUNCATE TABLE 地址备份表1';
          INSERT INTO 地址备份表1 SELECT * FROM 地址表1;
          COMMIT;
          --导入
          BEGIN
              EXECUTE IMMEDIATE 'ALTER TABLE 地址表1 DROP CONSTRAINT 主键1';
          EXCEPTION
              WHEN OTHERS THEN
                  NULL;    
          END;          EXECUTE IMMEDIATE 'ALTER TABLE 地址表1 TRUNCATE 分区.. ';          BEGIN
              EXECUTE IMMEDIATE '
              INSERT INTO 地址表1(ID, NAME, GRADE, PARENTID, ADDR) 
                   SELECT AG.ID, AG.NAME, NVL(AG.GRADE,-1), AG.PARENTID, AG.ADDR
                     FROM 源地址表';

              COMMIT; 
              DBMS_STATS.gather_table_stats(……);
      
              BEGIN
                  EXECUTE IMMEDIATE 'ALTER TABLE 地址表1 ADD CONSTRAINT 主键1
                                     USING INDEX TABLESPACE "INDEX" NOLOGGING';
                  DBMS_STATS.gather_index_stats(……);
              EXCEPTION
                  WHEN OTHERS THEN
                      NULL;    
              END;          EXCEPTION
              WHEN OTHERS THEN
                  --恢复
                  V_ERROR_MESSAGE := 'OTHER ERROR: '||substr(sqlerrm(SQLCODE),1,255);
                  INSERT INTO 日志表1;
                  EXECUTE IMMEDIATE 'TRUNCATE TABLE 地址表1';
                  INSERT INTO 地址表1 SELECT * FROM 地址备份表1;
                  COMMIT;
          
                  DBMS_STATS.gather_table_stats(……);                  BEGIN
                      EXECUTE IMMEDIATE 'ALTER TABLE 地址表1 ADD CONSTRAINT 主键1
                                               USING INDEX TABLESPACE "INDEX" NOLOGGING';
                      DBMS_STATS.gather_index_stats(……);
                  EXCEPTION
                      WHEN OTHERS THEN
                          NULL;    
                  END;          END;
      END IF;      INSERT INTO 日志表1;
      COMMIT;
      
  Exception  WHEN OTHERS THEN
    V_ERROR_MESSAGE := 'OTHER ERROR: '||substr(sqlerrm(SQLCODE),1,255);
    INSERT INTO 日志表1;
    COMMIT;
  END Etl_ADDR;
------------------------------------
 
提问:execute immediate 不是用来执行动态sql语句的吗,但是上面那个例子怎么用它来执行查询(select)、删除表的内容(truncate)、增加主键(alter)和插入数据(insert)
而同样的,存过里不也有单独的insert into语句(没有放在execute immediate里)吗,那针对上面标示为橙色的四个execute immediate的意义大家能解释一下吗?实在搞糊涂了

解决方案 »

  1.   

    ----execute immediate 不是用来执行动态sql语句的吗,但是上面那个例子怎么用它来执行查询(select)、删除表的内容(truncate)、增加主键(alter)和插入数据(insert)
    而同样的,存过里不也有单独的insert into语句(没有放在execute immediate里)吗,那针对上面标示为橙色的四个execute immediate的意义大家能解释一下吗?实在搞糊涂了这就是execute immediate动态的执行 select 、truncate、alter、insert 语句而已。
      

  2.   

    1. EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM 地址表1 WHERE ROWNUM<10' INTO V_CNT_AG;
    4. EXECUTE IMMEDIATE '
    INSERT INTO 地址表1(ID, NAME, GRADE, PARENTID, ADDR) 
    SELECT AG.ID, AG.NAME, NVL(AG.GRADE,-1), AG.PARENTID, AG.ADDR
    FROM 源地址表';这两个没有必要使用的,这完全是作者不好的编码习惯2. EXECUTE IMMEDIATE 'TRUNCATE TABLE 地址备份表1'
    3. EXECUTE IMMEDIATE 'ALTER TABLE 地址表1 DROP CONSTRAINT 主键1';
    存储过程里不能直接执行 truncate, alter 语句,所以只能使用动态语句来实现
      

  3.   


    如果表名是变量的话,不是固定的值,那么就有必要用EXECUTE IMMEDIATE了。
      

  4.   

    ADD:存储过程里不能直接使用DDL语句。如:
    ALTER ...
    CREATE ...
    TRUNCATE 等。