这可能是不可能的,但我希望看看是否有一种平易近人的方式来运行在线替换带有视图的表格。
对于分区等在线表重组,DBMS_REDEFINITION非常有效。但我想用(物化)视图替换表,因此DBMS_REDEFINITION似乎不合适。
在重命名期间,我没有任何约束,依赖或变异dml等担心;我只想在用视图替换表时保持目标SELECTable。一个拙劣的例子如下。
CREATE TABLE SCI_FI_MOVIE (
SCI_FI_MOVIE_ID NUMBER(10, 0) NOT NULL PRIMARY KEY,
NAME VARCHAR2(100) UNIQUE NOT NULL,
DIRECTOR VARCHAR2(100) NOT NULL,
REVIEW_SCORE NUMBER(1, 0) CHECK ( REVIEW_SCORE IN (1, 2, 3, 4, 5))
);
CREATE TABLE NO_SCORES_SCI_FI_MOVIE (
SCI_FI_MOVIE_ID NUMBER(10, 0) NOT NULL PRIMARY KEY,
NAME VARCHAR2(100) UNIQUE NOT NULL,
DIRECTOR VARCHAR2(100) NOT NULL
);
CREATE MATERIALIZED VIEW KUBRICK_SABOTAGE
(SCI_FI_MOVIE_ID, NAME, DIRECTOR, REVIEW_SCORE)
REFRESH COMPLETE ON COMMIT
AS
SELECT
SCI_FI_MOVIE_ID,
NAME,
DIRECTOR,
CASE WHEN DIRECTOR = 'KUBRICK'
THEN 5
ELSE 2 END AS REVIEW_SCORE
FROM NO_SCORES_SCI_FI_MOVIE;
INSERT INTO SCI_FI_MOVIE VALUES (1, 'Apollo 13', 'HOWARD', 5);
INSERT INTO SCI_FI_MOVIE VALUES (2, '2001: A Space Odyssey', 'KUBRICK', 4);
INSERT INTO NO_SCORES_SCI_FI_MOVIE VALUES (1, 'Apollo 13', 'HOWARD');
INSERT INTO NO_SCORES_SCI_FI_MOVIE VALUES (2, '2001: A Space Odyssey', 'KUBRICK');
COMMIT;
-- THEN WHAT STEPS TO REPLACE TABLE WITH VIEW?
在这个例子中,我想最终得到名为SCI_FI_MOVIE的MV,并将TABLE SCI_FI_MOVIE重命名为SCI_FI_MOVIE_TEMP或等待删除的内容。如果替换可以原子方式完成,则在替换原始表之前不存在要求MV存在
我想避免任何中断或妥协对象名称解析(CREATE PUBLIC SYNONYM
然后重命名原始文件将不起作用)
有没有干净的无停机时间吗?
我可以根据需要自由禁用日志记录,只读等任何内容;唯一的目标是在字典切换期间防止“ORA-00942:表或视图不存在”。我在11gR2上,但也欢迎12c解决方案。
非常感谢你的想法
答案 0 :(得分:3)
您不需要在线重新定义或任何聪明;你想要做的是通过ON PREBUILT TABLE
clause:
ON PREBUILT TABLE子句允许您将现有表注册为预初始化的物化视图。此子句对于在数据仓库环境中注册大型实例化视图特别有用。该表必须具有相同的名称,并且与生成的实例化视图位于相同的模式中。
如果删除了物化视图,则预先存在的表将恢复为其作为表的标识。
所以你可以这样做:
CREATE MATERIALIZED VIEW SCI_FI_MOVIE
(SCI_FI_MOVIE_ID, NAME, DIRECTOR, REVIEW_SCORE)
ON PREBUILT TABLE
REFRESH COMPLETE ON COMMIT
AS
SELECT
SCI_FI_MOVIE_ID,
NAME,
DIRECTOR,
CAST(CASE WHEN DIRECTOR = 'KUBRICK'
THEN 5
ELSE 2 END AS NUMBER(1,0)) AS REVIEW_SCORE
FROM NO_SCORES_SCI_FI_MOVIE;
Materialized view SCI_FI_MOVIE created.
需要CAST(... AS NUMBER(1,0))
才能使生成的数据类型与基础表匹配。
在构建MV时,表被锁定(由于没有数据收集或创建,因此几乎是即时的)所以在发生这种情况时对它进行查询只会暂时阻止。
视图将具有原始表值:
select * from SCI_FI_MOVIE;
SCI_FI_MOVIE_ID NAME DIRECTOR REVIEW_SCORE
--------------- ------------------------------ ---------- ------------
1 Apollo 13 HOWARD 5
2 2001: A Space Odyssey KUBRICK 4
...直到它被刷新,这个(在这个例子中)将在下一次提交:
INSERT INTO NO_SCORES_SCI_FI_MOVIE VALUES (3, 'Star Wars', 'LUCAS');
1 row inserted.
COMMIT;
select * from SCI_FI_MOVIE;
SCI_FI_MOVIE_ID NAME DIRECTOR REVIEW_SCORE
--------------- ------------------------------ ---------- ------------
1 Apollo 13 HOWARD 2
2 2001: A Space Odyssey KUBRICK 5
3 Star Wars LUCAS 2
对于普通(非物化视图),只要您可以创建公共同义词,就可以进行一些改组以实现相同的目的:
CREATE TABLE SCI_FI_MOVIE_TMP_TAB AS SELECT * FROM SCI_FI_MOVIE;
CREATE VIEW SCI_FI_MOVIE_TMP_VIEW AS SELECT * FROM SCI_FI_MOVIE_TMP_TAB;
CREATE PUBLIC SYNONYM SCI_FI_MOVIE FOR SCI_FI_MOVIE_TMP_VIEW;
ALTER TABLE SCI_FI_MOVIE RENAME TO SCI_FI_MOVIE_OLD;
CREATE VIEW SCI_FI_MOVIE AS
SELECT
SCI_FI_MOVIE_ID,
NAME,
DIRECTOR,
CAST(CASE WHEN DIRECTOR = 'KUBRICK'
THEN 5
ELSE 2 END AS NUMBER(1,0)) AS REVIEW_SCORE
FROM NO_SCORES_SCI_FI_MOVIE;
DROP PUBLIC SYNONYM SCI_FI_MOVIE;
DROP VIEW SCI_FI_MOVIE_TMP_VIEW;
DROP TABLE SCI_FI_MOVIE_TMP_TAB;
DROP TABLE SCI_FI_MOVIE_OLD;
这取决于how Oracle resolves schema object references。重命名原始表时,它无法再在当前架构(命名空间)中找到具有该名称的对象,并查找公共同义词,并愉快地使用它。创建的视图再次优先于公共同义词。