有一个问题,我找不到答案,有人可以帮助我吗?这是情况:
我有一个模式,那就是模板。
我想要这个模板有10个架构。
但是我希望每次更改模板架构的结构时(例如创建新列),都在与模板架构相关的所有架构中创建该列。
Oracle可以做到这一点吗?
答案 0 :(得分:2)
正如其他人所说,默认情况下在Oracle中不可能这样做。但是,如果您使用的是最新版本(12.2和更高版本),并且不介意支付多租户选项,则可以考虑使用application containers。这会将您的架构在单个DB中交换为相同的架构,但在不同的PDB中。应用程序容器允许您在父PDB中定义架构(包括表,视图,触发器等),并使每个修改都传播到PDB(在需要时同步每个PDB)。
答案 1 :(得分:0)
但是我希望每次更改模板架构的结构时(例如创建新列),都在与模板架构相关的所有架构中创建该列。
Oracle可以做到这一点吗?
不,不是。您需要在每个用户(也称为架构)拥有的表中单独创建列。
答案 2 :(得分:0)
正如Justin Cave所建议的那样,您的问题实际上是在为Oracle分区尖叫。
如果您没有获得分区许可,仍然可以使用旧的(但免费的!)方法来创建分区视图。
通过这种方法,您可以保持历史表不变(即不要回去向其添加新列)。相反,您将创建一个包含每个历史表的分区视图(通过UNION ALL
串联在一起)。视图定义可以为当年原始表中不存在的较新列提供值。
分区视图还具有以下优点:
以下是该方法的逐步介绍:
CREATE TABLE matt_data_2019
( id NUMBER NOT NULL,
creation_date DATE NOT NULL,
data_column1 NUMBER,
data_column2 VARCHAR2(200),
CONSTRAINT matt_data_2019 PRIMARY KEY ( id ),
CONSTRAINT matt_data_2019_c1 CHECK ( creation_date BETWEEN to_date('01-JAN-2019','DD-MON-YYYY') AND to_date('01-JAN-2020','DD-MON-YYYY') - interval '1' second )
);
CREATE TABLE matt_data_2020
( id NUMBER NOT NULL,
creation_date DATE NOT NULL,
data_column1 NUMBER,
data_column2 VARCHAR2(200),
data_column3 DATE, -- This is new for 2020
CONSTRAINT matt_data_2020 PRIMARY KEY ( id ),
CONSTRAINT matt_data_2020_c1 CHECK ( creation_date BETWEEN to_date('01-JAN-2020','DD-MON-YYYY') AND to_date('01-JAN-2021','DD-MON-YYYY') - interval '1' second )
);
请注意,2020年将增加一个新栏目,而2019年将不存在。
INSERT INTO matt_data_2019 ( id, creation_date, data_column1, data_column2 )
SELECT rownum id,
to_date('01-JAN-2019','DD-MON-YYYY') + (dbms_random.value(0, 365*24*60*60-1) / (365*24*60*60)), -- Some random date in 2019
dbms_random.value(0,1000),
lpad('2019',200,'X')
FROM dual
CONNECT BY rownum <= 100000;
INSERT INTO matt_data_2020 ( id, creation_date, data_column1, data_column2, data_column3 )
SELECT rownum id,
to_date('01-JAN-2020','DD-MON-YYYY') + (dbms_random.value(0, 365*24*60*60-1) / (365*24*60*60)), -- Some random date in 2020
dbms_random.value(0,1000),
lpad('2020',200,'X'),
to_date('01-JAN-2021','DD-MON-YYYY') + (dbms_random.value(0, 365*24*60*60-1) / (365*24*60*60)) -- Some random date in 2021
FROM dual
CONNECT BY rownum <= 100000;
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'MATT_DATA_2019');
EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'MATT_DATA_2020');
每次创建新表时,您都需要修改此视图。
CREATE OR REPLACE VIEW matt_data_v AS
SELECT 2019 source_year,
id,
creation_date,
data_column1,
data_column2,
NULL data_column3 -- data_column3 did not exist in 2019
FROM matt_data_2019
UNION ALL
SELECT 2020 source_year,
id,
creation_date,
data_column1,
data_column2,
data_column3 -- data_column3 did not exist in 2019
FROM matt_data_2020;
EXPLAIN PLAN SET STATEMENT_ID = 'MM' FOR SELECT * FROM MATT_DATA_V WHERE SOURCE_YEAR = 2020
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE','MM'));
Plan hash value: 393585474 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 110K| 15M| 620 (2)| 00:00:01 | | 1 | VIEW | MATT_DATA_V | 110K| 15M| 620 (2)| 00:00:01 | | 2 | UNION-ALL | | | | | | |* 3 | FILTER | | | | | | | 4 | TABLE ACCESS FULL| MATT_DATA_2019 | 71238 | 9530K| 596 (2)| 00:00:01 | | 5 | TABLE ACCESS FULL | MATT_DATA_2020 | 110K| 15M| 620 (2)| 00:00:01 | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - filter(NULL IS NOT NULL) Note ----- - dynamic statistics used: dynamic sampling (level=2)
...但是不是。该NULL IS NOT NULL
过滤条件将导致Oracle完全跳过2019表。
alter session set statistics_level = ALL;
SELECT * FROM MATT_DATA_V WHERE SOURCE_YEAR = 2020;
-- Be sure to fetch entire result set (e.g., scroll to the end in SQL*Developer)
SELECT *
FROM TABLE (DBMS_XPLAN.display_cursor (null, null,
'ALLSTATS LAST'));
SQL_ID 1u3nwcnxs20jb, child number 0 ------------------------------------- SELECT * FROM MATT_DATA_V WHERE SOURCE_YEAR = 2020 Plan hash value: 393585474 ------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 100K|00:00:00.21 | 5417 | | 1 | VIEW | MATT_DATA_V | 1 | 110K| 100K|00:00:00.21 | 5417 | | 2 | UNION-ALL | | 1 | | 100K|00:00:00.17 | 5417 | |* 3 | FILTER | | 1 | | 0 |00:00:00.01 | 0 | | 4 | TABLE ACCESS FULL| MATT_DATA_2019 | 0 | 71238 | 0 |00:00:00.01 | 0 | | 5 | TABLE ACCESS FULL | MATT_DATA_2020 | 1 | 110K| 100K|00:00:00.09 | 5417 | ------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - filter(NULL IS NOT NULL) Note ----- - dynamic statistics used: dynamic sampling (level=2)
以上结果显示了Oracle在我们不要求时如何跳过2019表。