Используя дату в контрольном ограничении, Oracle

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

ALTER TABLE Table1 ADD (CONSTRAINT GT_Table1_CloseDate CHECK (CloseDate > SYSDATE), CONSTRAINT LT_Table1_CloseDate CHECK (CloseDate  (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. 

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

 CREATE OR REPLACE TRIGGER trg_check_dates BEFORE INSERT OR UPDATE ON table1 FOR EACH ROW BEGIN IF( :new.CloseDate <= SYSDATE ) THEN RAISE_APPLICATION_ERROR( -20001, 'Invalid CloseDate: CloseDate must be greater than the current date - value = ' || to_char( :new.CloseDate, 'YYYY-MM-DD HH24:MI:SS' ) ); END IF; IF( :new.CloseDate > add_months(SYSDATE,12) ) THEN RAISE_APPLICATION_ERROR( -20002, 'Invalid CloseDate: CloseDate must be within the next year - value = ' || to_char( :new.CloseDate, 'YYYY-MM-DD HH24:MI:SS' ) ); END IF; IF( :new.StartDate <= add_months(:new.CloseDate,24) ) THEN RAISE_APPLICATION_ERROR( -20002, 'Invalid StartDate: StartDate must be within 24 months of the CloseDate - StartDate = ' || to_char( :new.StartDate, 'YYYY-MM-DD HH24:MI:SS' ) || ' CloseDate = ' || to_char( :new.CloseDate , 'YYYY-MM-DD HH24:MI:SS' ) ); END IF; END; 

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

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

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

Для 10g Release 2 (10.2) см. Ограничение, а для 11g Release 2 (11.2) см. Ограничение .

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

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

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

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

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

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

Запишите 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 

Вы можете добиться этого, когда будете немного обманывать:

 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 станет более умным и больше не позволит таких трюков.

Я не рекомендую использовать триггеры в качестве ограничения и создавать исключения. Вместо этого вы можете использовать столбец для хранения 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)))); 
  • Как разрешить ввод только цифр в jTextField?
  • Операция «Вставить, если не существует» в SQLite
  • Ограничить оси ggplot2 без удаления данных (внешние ограничения): увеличить
  • Уникальное ограничение, позволяющее пустым значениям в MySQL
  • Как добавить ограничения «на удаление каскада»?
  • Как использовать интерфейс как ограничение типа C #?
  • Использование переменной в предложении LIMIT в MySQL
  • Аннотации из javax.validation.constraints не работают
  • F # Статические ограничения типа пользователя
  • Как обрезать таблицу с ограниченным внешним ключом?
  • Ограничения на hibernate Ограничения И / ИЛИ комбинация
  • Давайте будем гением компьютера.