in order to make the following type of assertion
create assertion assert
check "EMPTY SET" = (select User
from Video
where date=current_date()
group by user
having count(*) >= 10
is this assertion right?
create assertion assert
check 0 = (select count(*)
from Video
where date=current_date()
group by user
having count(*) >= 10
For full details on
CREATE ASSERTION
see the ISO SQL-92 Standard spec.The
CHECK
definition should be in parentheses.CURRENT_DATE
does not have parentheses.USER
andDATE
are reserved words.SQL statements should be terminated with a semicolon character.
SQL Keywords should be in upper case.
Try something more like this:
You can test that the syntax is correct using the online Mimer SQL-92 Validator. However, you should also test your logic e.g.
CURRENT_DATE
is non-deterministic.Also, I don't think this
ASSERTION
will ever bite. When the cardinality of the subquery is less than 10 it will return zero rows and0 = empty set
will evaluate toUNKNOWN
. When the cardinality of the subquery is 10 or greater then the search condition will evaluateTRUE
. SQL-92 Standard statesNote you can replace your
CHECK (0 = (SELECT COUNT(*) FROM...))
construct withCHECK (NOT EXISTS (SELECT * FROM...))
, the latter of which I find easier to write.UPDATE:
As I said above, your logic appears flawed so it is hard to implement properly ;)
Let's say the rule is to limit Videos to 10 per user per day. Because this involves only a single table, it would be more appropriate to use a table-level
CHECK
constraint; such a constraint is checked when the table is updated which is sufficient in this case (there's no reason why it couldn't be anASSERTION
, though, which in theory could be checked each time any table in the schema is updated):UPDATE 2:
Consider again that a
CHECK
/ASSERTION
will only be checked when data in the table/schema is updated. The problem with usingCURRENT_DATE
(and other non-determninistic functions) in a constraint is that the business rule can be invalidated simply by the clock ticking over from one time period to the next but if the data hasn't been changed in that period then the data integrity failure will not be detected and the database will contain invalid data.Another consideration is what is meant by a year in context.
It could be the calendar year (1 Jan to 31 Dec inclusive) or other other fixed dates defined by enterprise (e.g. 1 Apr to 31 Mar inclusive), in which case grouping by year and user then counting is trivial.
A more interesting case is when the rule limits the tally for any 12 month period; extending this to both the past and future avoid the above 'non-deterministic' issue.
Consider a standard approach of using an auxiliary calendar table, containing one row for every day applicable to the enterprise, extended into the past and future only as far as required should still only comprise a few thousand rows. Each row would have the date as a key with a second column for that date plus one year (and if necessary you could fine tune the definition of 'a year' at one-day granularity!) The test for would involve joining to the Calendar table, grouping on the calendar date and user and counting e.g. something like this:
This could be put in a
CHECK (NOT EXISTS (...
constraint. This could still be a table-levelCHECK
constraint: because the Calendar table is an auxiliary table it would only be suject to infrequent controlled updates (but again could be anASSERTION
if required).