【问题标题】:What is the best way to handle this constraint in SQL Server 2005?在 SQL Server 2005 中处理此约束的最佳方法是什么?
【发布时间】:2009-04-14 19:30:14
【问题描述】:

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

我收到了详细 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

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

【问题讨论】:

  • 你们可以提供 DDL 吗?你的主键是什么?
  • 我以最简单的方式添加了 DDL... :)

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


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    可以像这样添加在 UDF 中实现的约束:

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

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

          【解决方案5】:

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

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

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

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

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

          OP cmets:

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

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

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

          Survey 是 Question 的误称吗?

          真的不清楚你要建模什么。

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

          【讨论】:

          • 不,你错过了它。调查:答案是 1:n。 “问题”是调查问题
          • 元组将是 (SurveyDomain.SurveyDomainId, Survey.Answer)
          • 如果有帮助,请忽略“问题”列。问题列仅仅是调查的“问题”文本!一项调查有 N 个答案!
          • 一项调查仅包含一个问题。调查是一个问题,问题是一个调查。再一次,假装“问题”列不存在。
          猜你喜欢
          • 2011-06-30
          • 1970-01-01
          • 2011-10-14
          • 1970-01-01
          • 1970-01-01
          • 2010-09-18
          • 1970-01-01
          • 2018-07-08
          • 1970-01-01
          相关资源
          最近更新 更多