在SQL中表达数据约束

时间:2009-02-02 15:14:52

标签: sql

我正在为我的妻子编写一份日程安排申请表,我遇到了以下问题。

我有一个可以用ActiveRecord术语描述的模式:

  • 每个资源都拥有并属于许多事件 s
  • 每个事件都拥有并属于许多资源,并且有很多 timespan s
  • 每个 timepan 属于事件,并且有三个属性: day start-time ,以及结束时间

我想对我的数据设置以下限制:

    A. For each timespan, timespan.start-time ≤ timespan.end-time
    B. For each event, for each t_a, t_bTIMESPANS(event), 
       either t_a = t_b
           or t_a.day ≠ t_b.day
           or t_a.end-time ≤ t_b.start-time
           or t_a.start-time ≥ t_b.end-time
    C. For each resource, for each e_a, e_bEVENTS(resource),
       either e_a = e_b
           or for each t_aTIMESPANS(e_a) and t_bTIMESPANS(e_b),
              either t_a.day ≠ t_b.day
                  or t_a.end-time ≤ t_b.start-time
                  or t_a.start-time ≥ t_b.end-time

(A)确保时间跨度良好,(B)确保事件不会发生自我冲突,(C)确保资源不会过度安排。

目前我正在应用层执行这些约束,但为了自学,我想知道是否可以将这些约束放在数据库层中。

我有什么方法可以在SQL中表达这些约束吗?

修改 所以我发现我想要的是SQL的CREATE ASSERTION语句(至少,对于那些简单的CHECK无法涵盖的语句),但它似乎不像任何支持它的RDBMS (at least, as of 2005

1 个答案:

答案 0 :(得分:2)

A很容易用时间表上的CHECK CONSTRAINT表示,因为每行都可以检查自身的一致性而不检查任何其他行。

B和C更复杂,需要从其他表中读取信息。在这种情况下(至少在SQL Server中),可以使用用户定义的函数(从当前行传递值)来检查其他表,或者可以使用TRIGGER来检查其他表表。

注意:在编写这样的触发器时,请记住触发器会为SQL语句触发一次。如果该语句INSERTUPDATE多行,则INSERTED表将包含多行,应使用适当的技术检查所有行以匹配您的域约束,例如{{ 1}}。

BTW:Joe Celko最近有good article个约束。