В настоящее время я разрабатываю базу данных, которая имеет дело со множеством временных данных. Следовательно, имеется довольно много столбцов, которые должны содержать временной интервал-подобных значений. Важно то, что каждое из этих значений должно вписываться в фиксированный набор числовых диапазонов. Таким образом, создание ограничений на уровне базы данных для обеспечения соблюдения этих проверок имеет большой смысл (а также предоставляет некоторые полезные отказоустойчивые функции).Определение диапазона ПРОВЕРКИ на столбцах INTERVAL (PostgreSQL)
Сначала я рассмотрел использование типа данных BIGINT
&, сохраняя интервалы в качестве временных меток UNIX. Это позволило бы мне написать несколько простых ограничений CHECK и просто сделать это. Однако исследование типа данных INTERVAL
, созданного PostgreSQL, казалось, раскрыло некоторые действительно полезные функции. Более того, использование этого, вероятно, имеет больше смысла с точки зрения семантики моего дизайна.
Самая большая проблема, с которой я столкнулся после перехода на INTERVAL
, заключается в том, что я не могу найти хороший и единообразный способ определения ограничений CHECK, упомянутых ранее.
Вот грубый пример того, что я пытаюсь сделать:
CREATE TABLE PURCHASE( PURCHASE_ID SERIAL, PURCHASE_STATE_TYPE_ID SMALLINT NOT NULL, CUSTOMER_ID INTEGER NOT NULL, ... COOLINGOFF_PERIOD INTERVAL(3) NOT NULL, CONSTRAINT PK_PURCHASE PRIMARY KEY(PURCHASE_ID), CONSTRAINT FK_PURCHASE_PURCHASE_STATE_TYPE_ID FOREIGN KEY(PURCHASE_STATE_TYPE_ID) REFERENCES PURCHASE_STATE_TYPE(PURCHASE_STATE_TYPE_ID) ON UPDATE CASCADE, ... CONSTRAINT CHK_PURCHASE_COOLINGOFF_PERIOD_IN_RANGE CHECK((EXTRACT(EPOCH FROM INTERVAL COOLINGOFF_PERIOD)) BETWEEN 0 AND 315400000) ... );
В этом случае мы имеем CHK_PURCHASE_COOLINGOFF_PERIOD_IN_RANGE
СНЕСК, который следит за соблюдением COOLINGOFF_PERIOD
каждого PURCHASE
падать от 0 до 10 лет.
К сожалению, хотя, приведенное выше утверждение DDL завершается с ошибкой синтаксиса: ERROR: syntax error at or near "COOLINGOFF_PERIOD".
я упускаю что-то здесь? Есть ли хороший и чистый (i.e декларативный) способ сделать это, или я должен вернуться к использованию BIGINT
вместо этого?
Что не так с 'между '0' :: interval и '10 years ':: interval'? –
Как писал @Daniel, используйте оператор BETWEEN, посмотрите эту рабочую демонстрацию: http://sqlfiddle.com/#!12/521a2 – krokodilko
@ DanielVérité, @kordirko Спасибо! Это именно то, что я искал :). Честно говоря, я не использовал тип «ИНТЕРВАЛ» все, что было раньше, поэтому у меня было немного мозгового пердуна в отношении этих ограничений. Я немного удивился тому, что вы можете использовать ключевое слово 'years' в определении так же, как это! Я заранее пробовал всевозможные комбинации и с любопытством не мог заставить их работать. Теперь, если кто-то из вас может опубликовать ваш комментарий в качестве полного ответа, я был бы рад принять его! –