【问题标题】:Scripted Conversion of Views to Materialized Views (Oracle)视图到实体化视图的脚本转换 (Oracle)
【发布时间】:2014-02-04 04:03:18
【问题描述】:

我们在某些环境中更喜欢使用物化视图,但常规应用程序使用常规视图。为了让事情变得更简单,我们希望我们的应用程序能够根据配置参数以自动方式将所有常规视图自动迁移到物化视图。

我已经编写了我认为让该脚本正常运行所需的大部分内容,但我在最后的润色上苦苦挣扎。可能还有一些我需要解决的逃逸问题。

目前,该脚本会创建一个名为“magic”的视图,然后尝试将其转换,但到目前为止,它还不能转换为物化视图阶段。我不确定我做错了什么。非常感谢任何帮助。

我看到的错误如下。

Error report:
ORA-00911: invalid character
ORA-06512: at line 49
ORA-00911: invalid character
00911. 00000 -  "invalid character"
*Cause:    identifiers may not start with any ASCII character other than
           letters and numbers.  $#_ are also allowed after the first
           character.  Identifiers enclosed by doublequotes may contain
           any character other than a doublequote.  Alternative quotes
           (q'#...#') cannot use spaces, tabs, or carriage returns as
           delimiters.  For all other contexts, consult the SQL Language
           Reference Manual.
*Action:
Attempting to drop materialized view named MAGIC
No materialized view found with name MAGIC
Attempting to drop view named MAGIC
Success.
Attempting to create materialized view named MAGIC
  CREATE MATERIALIZED VIEW "MYDB"."MAGIC" ("MAGIC") AS 
  SELECT 'MAGIC' FROM DUAL;

Failed to create materialized view, recreating original view MAGIC
ERROR: Could not recreate view named MAGIC.
SQL was:
  CREATE OR REPLACE FORCE VIEW "MYDB"."MAGIC" ("MAGIC") AS 
  SELECT 'MAGIC' FROM DUAL;

PL/SQL 代码如下。

clear;
SET serveroutput ON size 1000000;
/**
* Converts all views in the database to materialized views.
*/

CREATE OR REPLACE VIEW "MAGIC" ("MAGIC") AS SELECT 'MAGIC' FROM DUAL;

BEGIN
  FOR cur_rec IN ( SELECT object_name, object_type FROM user_objects WHERE object_type='VIEW' and object_name='MAGIC' )
  LOOP
    BEGIN
      FOR cur_view IN
      (SELECT TRIM( REPLACE( REPLACE( DBMS_METADATA.GET_DDL('VIEW', cur_rec.object_name), 'CREATE OR REPLACE FORCE VIEW', 'CREATE MATERIALIZED VIEW' ), 'CREATE OR REPLACE VIEW', 'CREATE MATERIALIZED VIEW' ) ) "MATERIALIZED_VIEW",
        TRIM( DBMS_METADATA.GET_DDL('VIEW', cur_rec.object_name) ) "VIEW"
      FROM DUAL
      )
      LOOP
        BEGIN
          BEGIN
            DBMS_OUTPUT.PUT_LINE( 'Attempting to drop materialized view named ' || cur_rec.object_name );
            EXECUTE IMMEDIATE 'drop materialized view ' || cur_rec.object_name;
            DBMS_OUTPUT.PUT_LINE( 'Success.' );
          EXCEPTION
          WHEN OTHERS THEN
            DBMS_OUTPUT.PUT_LINE( 'No materialized view found with name ' || cur_rec.object_name );
            IF SQLCODE != -12003 THEN
              RAISE;
            END IF;
          END;
          BEGIN
            DBMS_OUTPUT.PUT_LINE( 'Attempting to drop view named ' || cur_rec.object_name );
            EXECUTE IMMEDIATE 'drop view ' || cur_rec.object_name;
            DBMS_OUTPUT.PUT_LINE( 'Success.' );
          EXCEPTION
          WHEN OTHERS THEN
            DBMS_OUTPUT.PUT_LINE( 'No view found with name ' || cur_rec.object_name );
            IF SQLCODE != -942 THEN
              RAISE;
            END IF;
          END;
          -- create the view as a materialized view.
          BEGIN
            DBMS_OUTPUT.PUT_LINE( 'Attempting to create materialized view named ' || cur_rec.object_name );
            DBMS_OUTPUT.PUT_LINE( cur_view."MATERIALIZED_VIEW" );
            EXECUTE IMMEDIATE cur_view."MATERIALIZED_VIEW";
            DBMS_OUTPUT.PUT_LINE( 'Success.' );
          EXCEPTION
          WHEN OTHERS THEN
            BEGIN
              DBMS_OUTPUT.PUT_LINE( 'Failed to create materialized view, recreating original view ' || cur_rec.object_name );
              EXECUTE IMMEDIATE cur_view."VIEW";
            EXCEPTION
            WHEN OTHERS THEN
              DBMS_OUTPUT.PUT_LINE( 'ERROR: Could not recreate view named ' || cur_rec.object_name || '.' );
              DBMS_OUTPUT.PUT_LINE( 'SQL was:' || cur_view."VIEW" );
              RAISE;
            END;
          END;
        END;
      END LOOP;
    END;
  END LOOP;
END;

【问题讨论】:

    标签: sql oracle view plsql materialized-views


    【解决方案1】:

    更新 - 最终解决方案

    运行此脚本时数据库在服务器端崩溃,因为我的某些视图依赖于其他视图。我的印象是这是以多线程方式完成的,并且由于视图处于各种准备状态,导致服务器崩溃和烧毁。从顺序处理的角度来看,我看不出这怎么会失败。从属视图以物化视图或常规视图的形式存在。

    最后,这些时间可能会减少,这些值对我有用,但在撰写此答案时我还没有测试过较低的阈值。

    set serveroutput on size 1000000;
    /**
    * Converts all views in the database to materialized views.
    */
    begin
      dbms_metadata.set_transform_param(dbms_metadata.session_transform, 'SQLTERMINATOR', false );
      for cur_rec in ( SELECT object_name, object_type from user_objects where object_type='VIEW' )
      loop
        begin
          for cur_view in
          (select trim( replace( replace( dbms_metadata.get_ddl( 'VIEW', cur_rec.object_name ), 'CREATE OR REPLACE FORCE VIEW', 'CREATE MATERIALIZED VIEW' ), 'CREATE OR REPLACE VIEW', 'CREATE MATERIALIZED VIEW' ) ) "MATERIALIZED_VIEW",
            trim( dbms_metadata.get_ddl( 'VIEW', cur_rec.object_name ) ) "VIEW"
          from dual )
          loop
            begin
              begin
                execute immediate 'drop materialized view ' || cur_rec.object_name;
                dbms_lock.sleep(5);
              exception
              when others then
                if sqlcode != -12003 then
                  raise;
                end if;
              end;
              begin
                execute immediate 'drop view ' || cur_rec.object_name;
                dbms_lock.sleep(5);
              exception
              when others then
                if sqlcode != -942 then
                  raise;
                end if;
              end;
              -- create the view as a materialized view.
              begin
                dbms_output.put_line( 'Attempting to create materialized view named ' || cur_rec.object_name );
                execute immediate cur_view."MATERIALIZED_VIEW";
                dbms_lock.sleep(5);
              exception
              when others then
                begin
                  dbms_output.put_line( 'Failed to create materialized view, recreating original view ' || cur_rec.object_name );
                  dbms_output.put_line( 'Error was: ' || sqlerrm( sqlcode ) );
                  dbms_output.put_line( cur_view."MATERIALIZED_VIEW" );
                  execute immediate cur_view."VIEW";
                  dbms_lock.sleep(5);
                exception
                when others then
                  dbms_output.put_line( 'ERROR: Could not recreate view named ' || cur_rec.object_name || '.' );
                  dbms_output.put_line( 'SQL was:' || cur_view."VIEW" );
                  raise;
                end;
              end;
            end;
          end loop;
        end;
      end loop;
    end;
    

    【讨论】:

      【解决方案2】:

      问题在于它试图执行的 SQL:

      CREATE MATERIALIZED VIEW "MYDB"."MAGIC" ("MAGIC") AS 
      SELECT 'MAGIC' FROM DUAL;
      

      动态SQL应该是单条语句,不能有语句终止符/分隔符;这是它不喜欢的最后一个;

      在调用get_ddl() 之前,您可以通过在块中添加对set_transform_param() procedure 的调用来停止dbms_metadata 首先将其包含在DDL 中:

      dbms_metadata.set_transform_param(dbms_metadata.session_transform,
        'SQLTERMINATOR', false);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-02
        • 1970-01-01
        • 2019-05-26
        • 1970-01-01
        相关资源
        最近更新 更多