2

您能否分享一些关于 Oracle 中具有临时有效性的表的主键操作的信息?

我创建了一个具有以下架构的表

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

我有来自另一个表“OtherTable”的以下记录,我需要复制到 TemporalTable_1

 
客户ID | 客户名称 | 有效周期开始 | Valid_Period_end
------------------+------------------------+-------- -----------------+------------------------
00001 | 约翰·陈 | 2020 年 6 月 1 日 00:00:00 | 2020 年 6 月 9 日 23:59:59
00001 | 强尼陈 | 2020 年 6 月 10 日 00:00:00 | 空值

以下是我的脚本:

insert into TemporalTable_1 select * from OtherTable;

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

在执行插入语句之前,表是空白的。所以我的问题是为什么我不允许将该行复制到 TemporalTable_1 中,即使这些行具有不同的 valid_period。

是不是因为Oracle实际上并不关心主键上的有效期列?

提前致谢!

4

2 回答 2

3

可以肯定的是,暂时的有效性还没有具备原生处理主键等的能力。

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 列是隐藏的,这意味着我们使用它来协助我们实现该功能所需的查询转换,而不是添加主键。

于 2020-07-13T03:06:20.083 回答
1

期间名称(在您的情况下为 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。它们对于表中的所有行都是相同的。此外,在Philipp Salvisberg 的以下演示中,您可以看到 Oracle 中的 Temporal Validity 还不支持时间完整性约束,而且它甚至不支持对重叠期间的检查。所以你还不能创建这样的约束。但是您可以阅读此类事情的旧方法(例如,例如外键约束 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

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

于 2020-07-13T04:03:36.140 回答