Is this the right way to create an SQL statement?

to make the following type of statement

create assertion assert check "EMPTY SET" = (select User from Video where date=current_date() group by user having count(*) >= 10 

is this statement true?

 create assertion assert check 0 = (select count(*) from Video where date=current_date() group by user having count(*) >= 10 
+4
source share
1 answer

For more information on CREATE ASSERTION see SQL SQL-92 Standard Specification.

The definition of CHECK must be in parentheses.

CURRENT_DATE does not have parentheses.

USER and DATE are reserved words.

SQL statements must be terminated with a semicolon.

SQL keywords must be uppercase.

Try something else like this:

 CREATE ASSERTION assert CHECK (0 = ( SELECT COUNT(*) FROM Video WHERE my_date = CURRENT_DATE GROUP BY my_user HAVING COUNT(*) >= 10 )); 

You can check the syntax using the online Mimer SQL-92 Validator . However, you should also check your logic, for example. CURRENT_DATE not deterministic.

Also, I don't think this ASSERTION will ever bite. When the power of the subquery is less than 10, it will return zero rows and 0 = empty set will be evaluated to UNKNOWN . When the subquery power is 10 or higher, the search term will evaluate to TRUE . SQL-92 Standard State

An assertion fails if and only if the result of the evaluation of the search condition is incorrect.

Note that you can replace the CHECK (0 = (SELECT COUNT(*) FROM...)) construct with CHECK (NOT EXISTS (SELECT * FROM...)) , the last of which is easier for me to write.


UPDATE:

How to write an expression using CHECK DOES NOT EXIST?

As I said above, your logic seems erroneous, so it is difficult to implement it properly;)

Let's say the rule is to limit the video to 10 per user per day. Since this is associated with only one table, it would be more appropriate to use a CHECK constraint at the table level; this restriction is checked when the table is updated, which is sufficient in this case (there is no reason why it could not be ASSERTION , although theoretically it would be possible to check every time any table in the scheme is updated):

 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 )); 

UPDATE 2:

thank you, now let me say that we want to limit the video to 100 per user per year, in this case using current_date will be well, is not it?

Again, repeat that a CHECK / ASSERTION will only be checked when updating data in a table / chart. The problem with using CURRENT_DATE (and other non-integrated functions) in the restriction is that a business rule can be canceled simply by switching the clock from one period to another, but if the data has not been changed in this period, then a data integrity failure will not be detected , and the database will contain invalid data.

Another consideration is what is meant by one year in context.

This can be a calendar year (from January 1 to December 31 inclusive) or other other fixed dates defined by the company (for example, from April 1 to March 31 inclusive), in which case the grouping by year and user, then the calculation is trivial.

A more interesting case is when the rule limits the count for any 12-month period; extending this to both the past and the future, to avoid the aforementioned "non-deterministic" problem.

Consider the standard approach of using an auxiliary calendar table , containing one row for each day, applicable to the enterprise, expanded into the past and the future only as necessary should contain only a few thousand rows. Each row will have a date as a key with a second column for that date plus one year (and, if necessary, you can fine tune the definition of β€œyear” with one-day drill!). The test should include attaching a table to the calendar, grouping by calendar date and user, and counting, for example something like this:

 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; 

This can be placed in the CHECK (NOT EXISTS (... constraint CHECK (NOT EXISTS (... It can still be a CHECK constraint at the table level: since the calendar table is an auxiliary table, it will only be suitable for rare controlled updates (but may be ASSERTION if necessary).

+8
source

Source: https://habr.com/ru/post/1338626/


All Articles