Подробную информацию о CREATE ASSERTION
см. В спецификации стандарта ISO SQL-92.
Определение CHECK
должно быть в скобках.
CURRENT_DATE
не содержит скобок.
USER
и DATE
являются зарезервированными словами.
Операторы SQL должны заканчиваться точкой с запятой.
Ключевые слова SQL должны быть в верхнем регистре.
Попробуйте что-то вроде этого:
CREATE ASSERTION assert
CHECK (0 = (
SELECT COUNT(*)
FROM Video
WHERE my_date = CURRENT_DATE
GROUP
BY my_user
HAVING COUNT(*) >= 10
));
Вы можете проверить правильность синтаксиса, используя онлайн-мимер SQL-92Validator .Однако вам также следует проверить свою логику, например, CURRENT_DATE
является недетерминированным.
Кроме того, я не думаю, что это ASSERTION
когда-либо будет кусаться.Если мощность подзапроса меньше 10, он возвращает ноль строк, а 0 = empty set
оценивается как UNKNOWN
.Если мощность подзапроса равна 10 или больше, тогда условие поиска оценивается как TRUE
.Стандарт SQL-92 заявляет
Утверждение не выполняется тогда и только тогда, когда результат оценки условия поиска ложен.
Обратите внимание, что вы можете заменить CHECK (0 = (SELECT COUNT(*) FROM...))
создайте с CHECK (NOT EXISTS (SELECT * FROM...))
, последний из которых мне легче написать.
ОБНОВЛЕНИЕ:
Как мне написать утверждение, используя CHECK NOT EXISTS?
Как я уже говорил выше, ваша логика выглядит некорректной, поэтому ее трудно реализовать должным образом;)
Допустим, правило ограничивает количество видео до 10 на пользователя в день.Поскольку это касается только одной таблицы, было бы более целесообразно использовать ограничение на уровне таблицы CHECK
;такое ограничение проверяется при обновлении таблицы, что является достаточным в этом случае (однако нет никаких причин, по которым это не может быть ASSERTION
, что теоретически можно проверять каждый раз любую таблицу всхема обновлена):
ALTER TABLE Video ADD
CONSTRAINT video_limit_10_per_user_per_day
CHECK (NOT EXISTS (
SELECT v1.my_user, v1.my_date
FROM Video AS V1
GROUP BY v1.my_user, v1.my_date
HAVING COUNT(*) > 10
));
ОБНОВЛЕНИЕ 2:
спасибо, теперь давайте предположим, что мы хотим ограничить количество видео до 100 на пользователя в год, в данном случаеиспользование current_date было бы необходимо, не так ли?
Еще раз учтите, что CHECK
/ ASSERTION
будет проверяться только при обновлении данных в таблице / схеме.Проблема с использованием CURRENT_DATE
(и других недетерминистских функций) в ограничении состоит в том, что бизнес-правило может быть признано недействительным просто из-за того, что часы переключаются с одного периода времени на другой, но если данные в этом случае не изменилисьпериод, то сбой целостности данных не будет обнаружен, и база данных будет содержать недопустимые данные.
Еще одним соображением является то, что подразумевается под годом в контексте.
Это может быть календарный год (с 1 января по 31 декабря включительно) или другие фиксированные даты, определенные предприятием (например, с 1 апреля по 31 марта включительно), и в этом случае группировка по году и количеству пользователей, то подсчет тривиален,
Более интересный случай, когда правило ограничивает подсчет для любого 12-месячного периода;Распространение этого на прошлое и будущее позволяет избежать вышеуказанной «недетерминированной» проблемы.
Рассмотрим стандартный подход с использованием вспомогательной календарной таблицы , содержащей по одной строке на каждый день, применимый к предприятию, перенесенный в прошлое и будущее только настолько, насколько требуется, должен по-прежнему включать тольконесколько тысяч строкВ каждой строке будет указана дата в виде ключа со вторым столбцом для этой даты плюс один год (и, если необходимо, вы можете точно настроить определение «год» с однодневной детализацией!). Для теста будет необходимо присоединиться к календарю.таблица, группирующаяся по календарной дате и пользователю и подсчитывающая, например, что-то вроде этого:
SELECT C1.dt, V1.my_user
FROM Video AS V1
INNER JOIN Calendar AS C1
ON (V1.my_date BETWEEN C1.dt AND C1.dt_plus_one_year)
GROUP
BY C1.dt, V1.my_user
HAVING COUNT(*) > 100;
Это может быть помещено в ограничение CHECK (NOT EXISTS (...
.Это все еще может быть ограничение на уровне таблицы CHECK
: поскольку таблица Calendar является вспомогательной таблицей, она будет подвержена нечастым контролируемым обновлениям (но, опять же, может быть ASSERTION
, если потребуется).