Использование даты в проверочном ограничении, Oracle - PullRequest
9 голосов
/ 17 марта 2011

Я пытаюсь проверить добавить следующее ограничение, но Oracle возвращает ошибку, показанную ниже.

ALTER TABLE Table1
ADD (CONSTRAINT GT_Table1_CloseDate
CHECK (CloseDate > SYSDATE),
CONSTRAINT LT_Table1_CloseDate
CHECK (CloseDate <= SYSDATE + 365)),
CONSTRAINT GT_Table1_StartDate
CHECK (StartDate > (CloseDate + (SYSDATE + 730))));

Ошибка:

Error report:
SQL Error: ORA-02436: date or system variable wrongly specified in CHECK constraint
02436. 00000 -  "date or system variable wrongly specified in CHECK constraint"
*Cause:    An attempt was made to use a date constant or system variable,
           such as USER, in a check constraint that was not completely
           specified in a CREATE TABLE or ALTER TABLE statement.  For
           example, a date was specified without the century.
*Action:   Completely specify the date constant or system variable.
           Setting the event 10149 allows constraints like "a1 > '10-MAY-96'",
           which a bug permitted to be created before version 8.

Ответы [ 6 ]

16 голосов
/ 17 марта 2011

К сожалению, проверочное ограничение не может ссылаться на такую ​​функцию, как SYSDATE.Вам нужно будет создать триггер, который проверяет эти значения при возникновении DML, т.е.

14 голосов
/ 17 марта 2011

Вы не можете использовать SYSDATE в проверочном ограничении.Согласно документации

Условия проверочных ограничений не могут содержать следующие конструкции:

  • Подзапросы и скалярные выражения подзапросов
  • Вызовы функций, которые недетерминированный (CURRENT_DATE,
    CURRENT_TIMESTAMP, DBTIMEZONE,
    LOCALTIMESTAMP, SESSIONTIMEZONE,
    SYSDATE , SYSTIMESTAMP, UID, USER и * USERENV)
  • Разыменование столбцов REF (например, с помощью функции DEREF)
  • Вложенные столбцы или атрибуты таблицы
  • Псевдостолбцы CURRVAL, NEXTVAL, LEVEL илиROWNUM
  • Константы даты, которые не указаны полностью

Для 10g Выпуск 2 (10.2) , см. Ограничение , идля 11g Выпуск 2 (11.2) см. ограничение .

Помните, что ограничение целостности - это утверждение о табличных данных, которое всегда true.

В любом случае:Я не знаю точно, чего вы пытаетесь достичь, но я думаю, что вы можете использовать триггеры для этой цели.

5 голосов
/ 20 марта 2014

Запишите sysdate в столбец и используйте его для проверки. Этот столбец может быть вашим столбцом аудита (например, дата создания)

CREATE TABLE "AB_EMPLOYEE22"
(
   "NAME"     VARCHAR2 ( 20 BYTE ),
   "AGE"      NUMBER,
   "SALARY"   NUMBER,
   "DOB"      DATE,
   "DOJ"      DATE DEFAULT SYSDATE
);

Table Created    

ALTER TABLE "AB_EMPLOYEE22" ADD CONSTRAINT
AGE_CHECK CHECK((ROUND((DOJ-DOB)/365)) = AGE) ENABLE;

Table Altered
4 голосов
/ 17 марта 2011

Каждый раз при обновлении записи SYSDATE будет иметь другое значение. Поэтому ограничение будет проверяться по-разному каждый раз. По этой причине Oracle не разрешает использовать sysdate в ограничении.

Вы можете решить вашу проблему с помощью триггера, который проверяет, действительно ли CloseDate действительно изменился, и вызывает исключение, когда новое значение находится вне диапазона.

И: Что такое (StartDate > (CloseDate + (SYSDATE + 730))))? Вы не можете добавлять даты.

И: StartDate должно быть после CloseDate? Разве это не странно?

1 голос
/ 21 октября 2016

Этого можно добиться, если немного обмануть, например:

CREATE OR REPLACE FUNCTION SYSDATE_DETERMINISTIC RETURN DATE DETERMINISTIC IS
BEGIN
    RETURN SYSDATE;
END SYSDATE_DETERMINISTIC;
/

CREATE TABLE Table1 (
   s_date DATE, 
   C_DATE DATE GENERATED ALWAYS AS ( SYSDATE_DETERMINISTIC() ) 
);

ALTER TABLE Table1 ADD CONSTRAINT s_check CHECK ( s_date < C_DATE );

Конечно, функция SYSDATE_DETERMINISTIC является , а не детерминированной, но Oracle в любом случае позволяет объявить это.

Возможно, в будущих выпусках Oracle станет более умным и не допустит подобных уловок.

0 голосов
/ 22 мая 2017

Я не рекомендую петь триггеры как ограничение и вызывать исключения. Вместо этого вы можете использовать столбец для хранения SYSDATE в качестве даты регистрации (если она у вас уже есть, вы можете использовать ее)ограничение сравнивает этот столбец вместо SYSDATE

 ALTER TABLE Table1
 ADD (REGISTER_DATE DATE);

 CREATE OR REPLACE TRIGGER trg_check_dates
   BEFORE INSERT OR UPDATE ON table1
   FOR EACH ROW
 BEGIN
   :new.REGISTER_DATE := SYSDATE;
 END;

 ALTER TABLE Table1
 ADD (CONSTRAINT GT_Table1_CloseDate
 CHECK (CloseDate > REGISTER_DATE),
 CONSTRAINT LT_Table1_CloseDate
 CHECK (CloseDate <= REGISTER_DATE + 365)),
 CONSTRAINT GT_Table1_StartDate
 CHECK (StartDate > (CloseDate + (REGISTER_DATE + 730))));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...