为了做出以下类型的断言
create assertion assert
check "EMPTY SET" = (select User
from Video
where date=current_date()
group by user
having count(*) >= 10
Run Code Online (Sandbox Code Playgroud)
这个说法是对的吗?
create assertion assert
check 0 = (select count(*)
from Video
where date=current_date()
group by user
having count(*) >= 10
Run Code Online (Sandbox Code Playgroud)
one*_*hen 12
有关CREATE ASSERTIONISO 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
));
Run Code Online (Sandbox Code Playgroud)
您可以使用在线Mimer SQL-92 Validator测试语法是否正确.但是,您还应该测试您的逻辑,例如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
));
Run Code Online (Sandbox Code Playgroud)
更新2:
谢谢,现在让我们说我们想要将视频限制为每个用户每年100个,在这种情况下使用current_date是必要的不是吗?
再考虑到一CHECK/ ASSERTION时,在表/架构数据更新将只进行检查.CURRENT_DATE在约束中使用(和其他非确定性函数)的问题在于,业务规则可以简单地通过从一个时间段到下一个时间段的时钟滴答而无效,但是如果数据在该时间段内没有被更改,那么将无法检测到数据完整性故障,并且数据库将包含无效数据.
另一个考虑因素是一年的背景意义.
它可以是日历年(1月1日至12月31日)或企业定义的其他固定日期(例如4月1日至3月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;
Run Code Online (Sandbox Code Playgroud)
这可能会CHECK (NOT EXISTS (...受到限制.这可能仍然是一个表级CHECK约束:因为Calendar表是一个辅助表,它只会引发不频繁的受控更新(但ASSERTION如果需要,也可以是一个).