我们有某些环境喜欢使用物化视图,但常规应用程序使用常规视图。为了简化操作,我们希望应用程序根据配置参数自动将所有常规视图自动迁移到物化视图。
我已经写了我认为最需要的东西来使这个脚本工作,但我正在努力进行最后的接触。可能还有一些我需要解决的逃避问题。
现在,脚本会创建一个名为“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;
答案 0 :(得分:3)
问题在于它正在尝试执行的SQL:
CREATE MATERIALIZED VIEW "MYDB"."MAGIC" ("MAGIC") AS
SELECT 'MAGIC' FROM DUAL;
动态SQL应该是单个语句,不能有语句终止符/分隔符;这是它不喜欢的最终;
。
在致电dbms_metadata
之前,您可以通过在阻止set_transform_param()
procedure中添加对{{3}}的调用来阻止{DD}首先将其包含在DDL中:
get_ddl()
答案 1 :(得分:0)
更新 - 最终解决方案
运行此脚本时,数据库在服务器端崩溃,因为我的一些视图依赖于其他视图。我得到的印象是,这是以多线程方式完成的,并且导致服务器崩溃并在视图处于各种准备状态时刻录。从顺序处理的角度来看,我看不出这会如何失败。依赖视图既可以作为物化视图,也可以作为常规视图。
最后,这些时间可能会减少,这些值对我有用,但在撰写此答案时我没有测试过较低的阈值。
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;