2014-01-15 4 views
3

우리는 구체화 된보기의 사용을 선호하지만 일반 응용 프로그램은 일반보기를 사용합니다. 작업을 더 쉽게하기 위해 응용 프로그램이 구성 매개 변수를 기반으로 모든 일반보기를 자동으로 구체화 된보기로 자동으로 마이그레이션하도록합니다.뷰의 구체화 된 뷰 (Materialized Views) 로의 스크립트 변환 (Oracle)

필자는이 스크립트를 작동시키는 데 가장 필요한 것으로 생각하는 것을 작성했지만 최종 수정에 어려움을 겪고 있습니다. 아마 내가 도망 갈 필요가있는 탈출구가있을 수 있습니다.

이제는 스크립트가 '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; 

답변

3

문제는 실행하려고는 SQL 함께 :

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

동적 SQL은 하나의 문장이어야하며 성명 터미네이터/분리를 가질 수 없습니다; 그것은 최종 ; 싫어.

당신이 get_ddl()를 호출하기 전에, 당신의 블록의 set_transform_param() procedure에 대한 호출을 추가하여 처음에 DDL에 포함 dbms_metadata을 중지 할 수 있습니다

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

대단히 감사합니다. – mrswadge

0

UPDATE - 최종 솔루션

을 내 뷰의 일부가 다른 뷰에 의존하기 때문에이 스크립트를 실행할 때 데이터베이스가 서버 측에서 충돌했습니다. 필자는 이것이 다중 스레드 방식으로 이루어졌으며 뷰가 다양한 준비 상태에 있기 때문에 서버가 충돌하고 레코딩되는 것으로 나타났습니다. 순차적 처리 관점에서 볼 때 이것이 실패 할 수있는 방법을 알 수 없습니다. 종속 뷰는 구체화 된 뷰 또는 일반 뷰로 존재합니다.

마지막으로 이러한 시간이 줄어들 수 있습니다.이 값은 저에게 효과적 이었지만이 대답을 작성할 당시에는 낮은 임계 값을 테스트하지 않았습니다.

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; 
관련 문제