Oracle 11g在线重定义table查看

Oracle 11g online redefinition table to view

这可能是不可能的,但我希望看看是否有一种可行的方法来 运行 在线替换 table 视图。

对于联机table分区等重组DBMS_REDEFINITION效果很好。但是我想用(物化)视图替换 table,所以 DBMS_REDEFINITION 看起来不合适table。

在重命名过程中,我没有任何约束、依赖关系或变异 dml 等需要担心的问题;我只想在用视图替换 table 时保持目标 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 或任何待删除的名称结束。在替换原始 table 之前,没有任何要求存在 MV,如果替换可以自动完成

我想避免对对象名称解析造成任何干扰或妥协(CREATE PUBLIC SYNONYM 然后重命名原始名称在这里不起作用)

是否有干净的无停机方式来执行此操作?
我可以根据需要随意禁用日志记录、只读等;唯一的目标是在字典切换期间防止 "ORA-00942: table or view does not exist" 。我使用的是 11gR2,但也欢迎使用 12c 解决方案。

非常感谢您的想法

您不需要进行在线重新定义或任何巧妙的操作;您要执行的操作是通过 ON PREBUILT TABLE clause:

内置的

The ON PREBUILT TABLE clause lets you register an existing table as a preinitialized materialized view. This clause is particularly useful for registering large materialized views in a data warehousing environment. The table must have the same name and be in the same schema as the resulting materialized view.

If the materialized view is dropped, then the preexisting table reverts to its identity as a 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)) 才能使生成的数据类型匹配基础 table。

table 在构建 MV 时被锁定(这几乎是即时的,因为没有数据收集或创建)所以在发生这种情况时对它的查询只会短暂阻塞。

视图将具有原始 table 值:

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

对于普通(非物化视图),您可以做一些改组来实现相同的目的,只要您可以创建 public 同义词:

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。当您重命名原始 table 时,它在当前模式(命名空间)中不再找到具有该名称的对象,并寻找 public 同义词,并愉快地使用它。创建视图时,再次优先于 public 同义词。