-1

我有基于 SMS 的调查应用程序,它包含一个调查域和一个答案。

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

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

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

4

5 回答 5

2

当您覆盖 2 个表时,AFAIK 只有两种方法来执行此操作。

  1. 按照您的建议触发。
  2. 跨 3 列具有唯一约束的索引视图。

就可靠性而言,我会选择索引视图,但唯一的缺点是第三方很难理解。

于 2009-04-14T19:37:28.270 回答
1

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

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

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

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

于 2009-04-14T19:50:52.153 回答
0

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

于 2009-04-14T19:40:09.777 回答
0

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

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

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

于 2009-04-14T19:52:00.543 回答
-1

我认为您的意思是,对于任何活跃的问题,元组 (surveyDomain、surveyQuestion、surveyAnswer) 必须是唯一的?

或者换句话说,如果调查处于活动状态,survey:surveyanswer 是 1:1,即使survey:surveyanswer 设置为 1:many。

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

确实,除非我有误解,否则我很惊讶 Survey 有一个 Question 栏。我希望 Survey:Question 是 1:many(一项调查有很多问题)或者甚至 many:many,如果一个问题可以出现在多个调查中。

更一般地说,我怀疑弄清楚如何强制执行约束很困难并且需要触发器或用户定义的函数等“英雄”的原因,是模式无法准确建模您的问题域的症状。

OP评论:

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

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

但是如果设置了调查的活动位,应该只有一个答案吗?

调查是问题的误称吗?

目前还不清楚您要建模的内容。

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

于 2009-04-14T20:13:50.913 回答