以便进行以下类型的断言
create assertion assert
check "EMPTY SET" = (select User
from Video
where date=current_date()
group by user
having count(*) >= 10
这个断言是对的吗?
create assertion assert
check 0 = (select count(*)
from Video
where date=current_date()
group by user
having count(*) >= 10
答案 0 :(得分:10)
有关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
));
您可以使用在线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...))
,我发现后者更容易编写。
更新:
我应该如何使用编写断言 检查不存在?
正如我上面所说,你的逻辑看似有缺陷,所以很难正确实施;)
假设规则是将视频限制为每个用户每天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月1日至12月31日)或企业定义的其他固定日期(例如4月1日至3月31日),在这种情况下,按年份分组,然后按用户进行计数是微不足道的。
更有趣的情况是规则限制任何 12个月期间的计数;将此扩展到过去和未来都避免了上述“非确定性”问题。
考虑一个standard approach of using an auxiliary calendar table,其中包含适用于企业的每一天的一行,只有在需要时才会延伸到过去和未来,应该只包含几千行。每行都有一个日期作为键,该日期的第二列加上一年(如有必要,您可以按一天的粒度微调“一年”的定义!)测试将涉及加入日历表,在日历日期和用户上分组并计算例如像这样的东西:
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
)。