2016-03-17 3 views
0

Я создал таблицу с композитным уникальным ключом, как below--Oracle: Составной уникальный ключ с датой колонке

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: unique constraint (CDUREFDB.TEST11_IDX) violated

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

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

Это, что из-за DATE column рассматривается Date значение до секунд? Потому что я мог видеть ниже запрос возвращается в result--

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) имеет на нем раздел.

UPDATE::

В этой таблице мы имеем RANGE раздел на колонке ДАТА (CC).

И мы планируем периодически периодически удалять разделы (т. Е. Через несколько дней).

Так что если я не использую прямой CC в уникальном индексе (вместо того, чтобы делать 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 

ответ

1

date всегда имеет временную составляющую, так что ваши две строки имеют различные значения cc. Вы можете создать индекс на основе функций, основанный на значении trunc(cc), который установит компонент времени в полночь.

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

Конечно, это означает, что если вы хотите запрос использовать индекс, вы хотите, чтобы убедиться, что ваш предикат на trunc(cc), а не cc.

+0

Спасибо @ Justin. Таким образом, нет никакого влияния наличия раздела в этом столбце? Потому что мы будем периодически удалять данные из этой таблицы на основе 'range partition', которые мы будем вводить в столбце DATE. –

+1

@AshishPatil - Я вообще не был бы сумасшедшим в отношении наличия глобальных индексов на секционированной таблице, но у вас это есть либо с индексом, который вы изначально создали, либо с индексом на основе функций. Я бы ожидал, что либо придется перестроить после того, как разделы будут удалены. Теперь, если ваш фактический индекс был локальным индексом (который, как я ожидал бы, потребует, чтобы 'cc' был ведущим столбцом), тогда у вас есть другой вопрос. В этом случае имеет смысл добавить виртуальный столбец в 'trunc (cc)' и разбить таблицу на это. –

+0

Спасибо @JustinCave снова. Я установил столбец DATE как виртуальный и теперь могу удалить раздел, а также могу использовать только DATE в качестве члена в составе уникального ключа. –

Смежные вопросы