具有时间有效性的 Oracle table 的主键违规
Primary key violation for Oracle table with temporal validity
能否请您分享一些关于 Table 上具有 Oracle 时间有效性的主键操作的信息?
我创建了一个具有以下架构的 table
Create table TemporalTable_1 (
Customer_ID number(8),
Customer_name varchar2(100),
valid_period_start timestamp,
valid_period_end timestamp,
period for valid_period(valid_period_start, valid_period_end),
constraint TemporalTable_1_PK primary key (Customer_ID , VALID_PERIOD)
)
我有来自另一个 table“其他Table”的记录,我需要复制到 TemporalTable_1
Customer_ID | Customer_name | Valid_period_start | Valid_Period_end
------------------+----------------------+-------------------------+-----------------------
00001 | John Chan | 01 JUN 2020 00:00:00 | 09 JUN 2020 23:59:59
00001 | Johnny Chan | 10 JUN 2020 00:00:00 | Null
以下是我的脚本:
insert into TemporalTable_1 select * from OtherTable;
ORA-00001: 违反唯一约束 (TemporalTable_1)
执行插入语句前,table为空白。所以我的问题是为什么不允许我将行复制到 TemporalTable_1 即使行有不同的 valid_period.
难道是因为Oracle其实并不关心主键上的有效期列?
提前致谢!
非常确定时间有效性还没有配备以本地处理主键等。
SQL> Create table TemporalTable_1 (
2 Customer_ID number(8),
3 Customer_name varchar2(100),
4 valid_period_start timestamp,
5 valid_period_end timestamp,
6 period for valid_period(valid_period_start, valid_period_end),
7 constraint TemporalTable_1_PK primary key (Customer_ID , VALID_PERIOD)
8 );
Table created.
SQL> select column_name, hidden_column
2 from user_tab_cols
3 where table_name = 'TEMPORALTABLE_1'
4 order by column_id;
COLUMN_NAME HID
------------------------------ ---
CUSTOMER_ID NO
CUSTOMER_NAME NO
VALID_PERIOD_START NO
VALID_PERIOD_END NO
VALID_PERIOD YES
VALID_PERIOD 列是隐藏的,这意味着我们使用它来协助我们实现该功能所需的查询转换,而不是添加主键。
期间名称(VALID_PERIOD 在您的情况下)列仅包含您的期间 ID。
检查此脚本及其输出:
--drop table TemporalTable purge;
-- formatting for sqlplus:
col periodname for a20;
col constraint_name for a20;
col search_condition_vc for a80;
col valid_period_start for a16;
col valid_period_end for a16;
col PERIODSTART for a20;
col PERIODEND for a20;
alter session set nls_timestamp_format='yyyy-mm-dd hh24:mi';
-- end of formatting
Create table TemporalTable (
Customer_ID number(8),
Customer_name varchar2(10)
);
alter table TemporalTable add (
valid_period_start timestamp,
valid_period_end timestamp,
period for valid_period(valid_period_start, valid_period_end)
);
ALTER TABLE TemporalTable ADD (
vt_start DATE,
vt_end DATE,
PERIOD FOR vt (vt_start, vt_end)
);
-- inserting overlapping records:
insert into TemporalTable
select 1, 'A' , date'2020-01-01', date'2020-01-10', date'2020-01-01', date'2020-01-10' from dual union all
select 1, 'B' , date'2020-01-05', date'2020-01-08', date'2020-01-01', date'2020-01-10' from dual
/
commit;
-- check valid_period and vt hidden columns:
select tt.*,valid_period,vt from TemporalTable tt
/
select *
from TemporalTable
AS OF PERIOD FOR valid_period DATE '2020-01-06'
/
select
constraint_name,
constraint_type,
search_condition_vc
from user_constraints c
where table_name='TEMPORALTABLE';
select * from sys.SYS_FBA_PERIOD
where obj#=(select object_id from user_objects where object_name='TEMPORALTABLE');
如您所见,我添加了 2 个有效期:VALID_PERIOD 与您的情况和 VT 一样。
请注意,隐藏列 VALID_PERIOD 和 VT 仅包含它们的 ID。 table 中的所有行都相同。此外,在 the following presentation by Philipp Salvisberg 中,您可以看到 Oracle 中的时间有效性尚不支持时间完整性约束,而且它甚至不支持检查重叠时间段。
所以你还不能创建这样的约束。但是你可以阅读这些东西的旧方法(例如,像外键约束 START_DATE -> prev(END_DATE) 和 ID 上的唯一约束,START_DATE)
输出:
CUSTOMER_ID CUSTOMER_N VALID_PERIOD_STA VALID_PERIOD_END VT_START VT_END VALID_PERIOD VT
----------- ---------- ---------------- ---------------- ------------------- ------------------- ------------ ----------
1 A 2020-01-01 00:00 2020-01-10 00:00 2020-01-01 00:00:00 2020-01-10 00:00:00 726847999 726848005
1 B 2020-01-05 00:00 2020-01-08 00:00 2020-01-01 00:00:00 2020-01-10 00:00:00 726847999 726848005
CUSTOMER_ID CUSTOMER_N VALID_PERIOD_STA VALID_PERIOD_END VT_START VT_END
----------- ---------- ---------------- ---------------- ------------------- -------------------
1 A 2020-01-01 00:00 2020-01-10 00:00 2020-01-01 00:00:00 2020-01-10 00:00:00
1 B 2020-01-05 00:00 2020-01-08 00:00 2020-01-01 00:00:00 2020-01-10 00:00:00
CONSTRAINT_NAME C SEARCH_CONDITION_VC
-------------------- - --------------------------------------------------------------------------------
VALID_PERIOD52D1FF C (VALID_PERIOD_START < VALID_PERIOD_END) and (VALID_PERIOD > 0)
VT52D205 C (VT_START < VT_END) and (VT > 0)
OBJ# PERIODNAME FLAGS PERIODSTART PERIODEND SPARE
---------- -------------------- ---------- -------------------- -------------------- ----------
89220 VALID_PERIOD 0 VALID_PERIOD_START VALID_PERIOD_END
89220 VT 0 VT_START VT_END
能否请您分享一些关于 Table 上具有 Oracle 时间有效性的主键操作的信息?
我创建了一个具有以下架构的 table
Create table TemporalTable_1 (
Customer_ID number(8),
Customer_name varchar2(100),
valid_period_start timestamp,
valid_period_end timestamp,
period for valid_period(valid_period_start, valid_period_end),
constraint TemporalTable_1_PK primary key (Customer_ID , VALID_PERIOD)
)
我有来自另一个 table“其他Table”的记录,我需要复制到 TemporalTable_1
Customer_ID | Customer_name | Valid_period_start | Valid_Period_end ------------------+----------------------+-------------------------+----------------------- 00001 | John Chan | 01 JUN 2020 00:00:00 | 09 JUN 2020 23:59:59 00001 | Johnny Chan | 10 JUN 2020 00:00:00 | Null
以下是我的脚本:
insert into TemporalTable_1 select * from OtherTable;
ORA-00001: 违反唯一约束 (TemporalTable_1)
执行插入语句前,table为空白。所以我的问题是为什么不允许我将行复制到 TemporalTable_1 即使行有不同的 valid_period.
难道是因为Oracle其实并不关心主键上的有效期列?
提前致谢!
非常确定时间有效性还没有配备以本地处理主键等。
SQL> Create table TemporalTable_1 (
2 Customer_ID number(8),
3 Customer_name varchar2(100),
4 valid_period_start timestamp,
5 valid_period_end timestamp,
6 period for valid_period(valid_period_start, valid_period_end),
7 constraint TemporalTable_1_PK primary key (Customer_ID , VALID_PERIOD)
8 );
Table created.
SQL> select column_name, hidden_column
2 from user_tab_cols
3 where table_name = 'TEMPORALTABLE_1'
4 order by column_id;
COLUMN_NAME HID
------------------------------ ---
CUSTOMER_ID NO
CUSTOMER_NAME NO
VALID_PERIOD_START NO
VALID_PERIOD_END NO
VALID_PERIOD YES
VALID_PERIOD 列是隐藏的,这意味着我们使用它来协助我们实现该功能所需的查询转换,而不是添加主键。
期间名称(VALID_PERIOD 在您的情况下)列仅包含您的期间 ID。 检查此脚本及其输出:
--drop table TemporalTable purge;
-- formatting for sqlplus:
col periodname for a20;
col constraint_name for a20;
col search_condition_vc for a80;
col valid_period_start for a16;
col valid_period_end for a16;
col PERIODSTART for a20;
col PERIODEND for a20;
alter session set nls_timestamp_format='yyyy-mm-dd hh24:mi';
-- end of formatting
Create table TemporalTable (
Customer_ID number(8),
Customer_name varchar2(10)
);
alter table TemporalTable add (
valid_period_start timestamp,
valid_period_end timestamp,
period for valid_period(valid_period_start, valid_period_end)
);
ALTER TABLE TemporalTable ADD (
vt_start DATE,
vt_end DATE,
PERIOD FOR vt (vt_start, vt_end)
);
-- inserting overlapping records:
insert into TemporalTable
select 1, 'A' , date'2020-01-01', date'2020-01-10', date'2020-01-01', date'2020-01-10' from dual union all
select 1, 'B' , date'2020-01-05', date'2020-01-08', date'2020-01-01', date'2020-01-10' from dual
/
commit;
-- check valid_period and vt hidden columns:
select tt.*,valid_period,vt from TemporalTable tt
/
select *
from TemporalTable
AS OF PERIOD FOR valid_period DATE '2020-01-06'
/
select
constraint_name,
constraint_type,
search_condition_vc
from user_constraints c
where table_name='TEMPORALTABLE';
select * from sys.SYS_FBA_PERIOD
where obj#=(select object_id from user_objects where object_name='TEMPORALTABLE');
如您所见,我添加了 2 个有效期:VALID_PERIOD 与您的情况和 VT 一样。 请注意,隐藏列 VALID_PERIOD 和 VT 仅包含它们的 ID。 table 中的所有行都相同。此外,在 the following presentation by Philipp Salvisberg 中,您可以看到 Oracle 中的时间有效性尚不支持时间完整性约束,而且它甚至不支持检查重叠时间段。 所以你还不能创建这样的约束。但是你可以阅读这些东西的旧方法(例如,像外键约束 START_DATE -> prev(END_DATE) 和 ID 上的唯一约束,START_DATE)
输出:
CUSTOMER_ID CUSTOMER_N VALID_PERIOD_STA VALID_PERIOD_END VT_START VT_END VALID_PERIOD VT
----------- ---------- ---------------- ---------------- ------------------- ------------------- ------------ ----------
1 A 2020-01-01 00:00 2020-01-10 00:00 2020-01-01 00:00:00 2020-01-10 00:00:00 726847999 726848005
1 B 2020-01-05 00:00 2020-01-08 00:00 2020-01-01 00:00:00 2020-01-10 00:00:00 726847999 726848005
CUSTOMER_ID CUSTOMER_N VALID_PERIOD_STA VALID_PERIOD_END VT_START VT_END
----------- ---------- ---------------- ---------------- ------------------- -------------------
1 A 2020-01-01 00:00 2020-01-10 00:00 2020-01-01 00:00:00 2020-01-10 00:00:00
1 B 2020-01-05 00:00 2020-01-08 00:00 2020-01-01 00:00:00 2020-01-10 00:00:00
CONSTRAINT_NAME C SEARCH_CONDITION_VC
-------------------- - --------------------------------------------------------------------------------
VALID_PERIOD52D1FF C (VALID_PERIOD_START < VALID_PERIOD_END) and (VALID_PERIOD > 0)
VT52D205 C (VT_START < VT_END) and (VT > 0)
OBJ# PERIODNAME FLAGS PERIODSTART PERIODEND SPARE
---------- -------------------- ---------- -------------------- -------------------- ----------
89220 VALID_PERIOD 0 VALID_PERIOD_START VALID_PERIOD_END
89220 VT 0 VT_START VT_END