简体   繁体   English

具有时间有效性的 Oracle 表的主键违规

[英]Primary key violation for Oracle table with temporal validity

Could you please share me some light regarding to primary key operation on Table with Temporal Validity in Oracle?您能否分享一些关于 Oracle 中具有临时有效性的表的主键操作的信息?

I have created an table with following schema我创建了一个具有以下架构的表

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)
)

I have following records from another table "OtherTable" and I need to copy into the TemporalTable_1我有来自另一个表“OtherTable”的以下记录,我需要复制到 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

Following is my script:以下是我的脚本:

insert into TemporalTable_1 select * from OtherTable;

ORA-00001: unique constraint (TemporalTable_1) violated ORA-00001: 违反了唯一约束 (TemporalTable_1)

Before execute the insert statement, the table was blank.在执行插入语句之前,表是空白的。 So my question is why I am not allowed copy the row into the TemporalTable_1 even the rows have different valid_period.所以我的问题是为什么我不允许将该行复制到 TemporalTable_1 中,即使这些行具有不同的 valid_period。

Is it because Oracle actually didn't care about the valid period column on the primary key?是不是因为 Oracle 实际上并不关心主键上的有效期列?

Thanks in advance!提前致谢!

Pretty sure that temporal validity is not yet equipped to natively handle primary keys and the like.可以肯定的是,暂时的有效性还没有具备原生处理主键等的能力。

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 

The VALID_PERIOD column is hidden, which means we're using it to assist with our implementation of the query transformation needed for the feature, not to add primary keys on. VALID_PERIOD 列是隐藏的,这意味着我们使用它来协助我们实现该功能所需的查询转换,而不是添加主键。

Period name(VALID_PERIOD in your case) columns contains just ID of your period.期间名称(在您的情况下为 VALID_PERIOD)列仅包含您的期间的 ID。 Check this script and its' output:检查此脚本及其'output:

 --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');

As you can see I added 2 validity periods: VALID_PERIOD as in your case and VT.如您所见,我添加了 2 个有效期:VALID_PERIOD 和 VT。 Notice that hidden columns VALID_PERIOD and VT contains just their ID.请注意,隐藏列 VALID_PERIOD 和 VT 仅包含它们的 ID。 They are the same for all rows in the table.它们对于表中的所有行都是相同的。 Moreover in the following presentation by Philipp Salvisberg you can see that Temporal Validity in Oracle doesn't support yet temporal integrity constraints yet and moreover it doesn't even support checks for overlapping periods.此外, 在 Philipp Salvisberg 的以下演示文稿中,您可以看到 Oracle 中的时间有效性还不支持时间完整性约束,而且它甚至不支持对重叠期间的检查。 So you can't create such constraints yet.所以你还不能创建这样的约束。 But you can read old methods for such things (for example, like foreign key constraints START_DATE -> prev(END_DATE) and unique contraint on ID, START_DATE)但是您可以阅读此类事情的旧方法(例如,例如外键约束 START_DATE -> prev(END_DATE) 和 ID 的唯一约束,START_DATE)

Output: Output:

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

https://www.doag.org/formes/pubfiles/5217205/2013-DEV-Philipp_Salvisberg-Multi-temporal_Database_Features_in_Oracle_12c-Praesentation.pdf https://www.doag.org/formes/pubfiles/5217205/2013-DEV-Philipp_Salvisberg-Multi-temporal_Database_Features_in_Oracle_12c-Praesentation.Z437175BA4191210EE004E1D937494D

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM