在SQL Server 2005中处理此约束的最佳方法是什么?

时间:2009-04-14 19:30:14

标签: sql sql-server sql-server-2005 triggers constraints

我有基于短信的调查应用程序,它接受调查域和答案。

我收到了详细的DDL请求,所以....数据库看起来像this

SurveyAnswer.Answer在该SurveyDomain的所有有效调查中必须是唯一的。在SQL术语中,这应该总是返回0..1行:

select * from survey s, surveyanswer sa
where s.surveyid = sa.surveyid and
      s.active = 1 and
      s.surveydomainid = @surveydomainid
      sa.answer = @answer

我计划在应用程序级别处理此约束,但也希望强制执行某些数据库完整性。做这个的最好方式是什么?触发?在约束中可能吗?

5 个答案:

答案 0 :(得分:2)

当你涉及2个表时,AFAIK只有2种方法来强制执行此操作。

  1. 按照建议触发。
  2. 在3列中具有唯一约束的索引视图。
  3. 就可靠性而言,我会选择索引视图,但唯一的缺点是第三方难以理解。

答案 1 :(得分:1)

可以添加在UDF中实现的约束,如下所示:

alter table MyTable add constraint complexConstraint
check (dbo.complexConstraintFct()=0)

其中complexConstraintFct是包含其他表的查询的函数。然而,这种方法存在一些问题,因为检查约束被设计为一次在单行上进行评估,但更新一次可以影响更多行。

所以,底线是:坚持使用触发器

答案 2 :(得分:0)

假设您正在使用存储过程来执行DML操作,您可以向SP添加一个保护子句,该子句为调查添加答案以检查是否存在等效答案。然后,您可以抛出异常或返回状态代码,以指示无法添加答案。

答案 3 :(得分:0)

您不能在行级别(例如CHECK约束)执行此操作,因此您必须拥有可以查看所有行的内容

触发器可以发送“好”消息,但它们在DML语句之后运行。你可以很好地控制处理。

索引视图会阻止DML语句,但会显示技术错误消息。这是一个额外的对象和索引来维护。

答案 4 :(得分:-1)

我认为你所说的是,对于任何活跃的问题,元组(surveyDomain,surveyQuestion,surveyAnswer)必须是唯一的吗?

或者换句话说,调查:如果调查活跃,surveyanswer是1:1,即使调查:surveyanswer设置为1:很多。

如果是这样,答案是改变你的表格结构。添加一个可空的activeAnswerId列进行调查将有效地使关系1:1;您现有的约束唯一SurveyId(或唯一的SurveyId,SurvetDomainId)就足以强制执行唯一性。

事实上,除非我误解,否则我很惊讶Survey有一个问题专栏;我希望Survey:Question为1:很多(调查有很多问题),甚至很多:很多,如果一个问题可以出现在多个调查中。

更一般地说,我怀疑找出如何强制执行约束的原因很困难,并且需要像触发器或用户定义函数这样的“英雄”,这是模式的一个症状,不能准确地模拟您的问题域。

OP评论:

  不,你错过了。调查:答案是1:n。 “问题”是调查问题 - 元组将是(SurveyDomain.SurveyDomainId,Survey.Answer)

你的意思是,对于每个域名,最多只有一个答案?再次,看看你的架构,它充其量是误导。 SurveyDomain有很多调查(每个都有一个问题列),调查有很多答案? (Schema

但是如果设置了Survey的有效位,那么应该只有一个Answer?

调查是否是一个用词不当的问题?

目前还不清楚你想要建模的是什么。

同样,如果添加约束很难,则表明您的模型不起作用。