【问题标题】:Oracle: Composite unique key with Date columnOracle:具有日期列的复合唯一键
【发布时间】:2016-03-17 20:34:58
【问题描述】:

我创建了一个具有复合唯一键的表,如下所示--

create table test11 
(
     aa number, 
     bb varchar2(10),
     cc DATE, 
     dd number,
     ee NUMBER
);

CREATE UNIQUE INDEX TEST11_IDX ON TEST11 (AA,BB,CC);

现在,每当我尝试插入数据时,都会出现以下错误:

ORA-00001:违反了唯一约束 (CDUREFDB.TEST11_IDX)

INSERT INTO TEST11 VALUES (1, 'AA', SYSDATE, 1, 1);
commit;

INSERT INTO TEST11 VALUES (1, 'AA', SYSDATE, 1, 1);
commit;

那是因为DATE 列正在考虑Date 值直到几秒钟? 因为我可以看到下面的查询返回的是结果--

select to_char(CC,'DD-Mon-YY HH:Mi:SS AM') from test11;

TO_CHAR(CC,'DD-MON-YYHH:MI:SSAM')
---------------------------------
17-Mar-16 04:28:37 PM             
17-Mar-16 04:28:43 PM   

那么,为了只将日期值(不是小时、分钟、秒精度)视为唯一的关​​键成员,可以做些什么。

另外,DATE 上面的列(CC)上有分区。

更新:

在这张表中,我们在 DATE 列 (CC) 上有 RANGE 分区。

我们计划定期删除分区(即间隔几天后)。

因此,如果我不在唯一索引中使用直接 CC(而不是按照 Justin 的建议进行 trunc),那么如果我在删除某些旧分区后尝试插入数据,则会收到 ORA-01502: index 'CDUREFDB.TEST111_IDX' or partition of such index is in unusable state 错误。

UPDATE_1 根据下面的@Justin 建议,此问题已解决,创建如下虚拟列:

CREATE TABLE TEST11
  (
    AA NUMBER,
    BB VARCHAR2(10),
    CC DATE,
    DD NUMBER ,
    EE NUMBER,
    FF DATE generated always AS (TRUNC(CC)) virtual
  )
  PARTITION BY RANGE
  (
    FF
  )
  INTERVAL
  (
    NUMTODSINTERVAL(1,'DAY')
  )
  (
    PARTITION partition_test_1 VALUES LESS THAN (TO_DATE('01-APR-2006','dd-MON-yyyy'))
  );



CREATE UNIQUE INDEX TEST111_IDX ON TEST11 (AA,BB,FF) LOCAL;  -- creating unique local index

【问题讨论】:

    标签: oracle11g unique-constraint


    【解决方案1】:

    date 始终具有时间分量,因此您的两行具有不同的 cc 值。您可以根据 trunc(cc) 值创建一个基于函数的索引,该值会将时间组件设置为午夜。

    CREATE UNIQUE INDEX TEST11_IDX 
        ON TEST11 (AA,BB,trunc(CC));
    

    当然,这意味着如果您希望查询使用索引,则需要确保您的谓词位于trunc(cc) 而不是cc

    【讨论】:

    • 谢谢@贾斯汀。那么对该列进行分区没有影响吗?因为我们将根据range partition 定期从该表中删除数据,我们将在 DATE 列上施加这些数据。
    • @AshishPatil - 我通常不会对分区表上的全局索引感到疯狂,但您可以使用最初创建的索引或基于函数的索引。我希望在删除分区后需要重建任何一个。现在,如果您的实际索引是本地索引(我希望 cc 成为前导列),那么您有一个完全不同的问题。在这种情况下,在trunc(cc) 上添加一个虚拟列并以此对表进行分区可能是有意义的。
    • 再次感谢@JustinCave。我已将 DATE 列设为虚拟,现在能够删除分区,并且我能够确保仅使用 DATE 作为唯一键组合的成​​员。
    猜你喜欢
    • 1970-01-01
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 2017-02-03
    • 1970-01-01
    • 2019-06-14
    • 2016-01-09
    • 1970-01-01
    相关资源
    最近更新 更多