简体   繁体   English

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

[英]What is the best way to handle this constraint in SQL Server 2005?

I have SMS based survey application which takes in a survey domain, and a answer. 我有一个基于SMS的调查应用程序,它包含一个调查域和一个答案。

I've gotten requests for detailed DDL, so.... The database looks like this 我已经收到了详细DDL的请求,所以....数据库看起来像这样

SurveyAnswer.Answer must be unique within all active Surveys for that SurveyDomain. SurveyAnswer.Answer在该SurveyDomain的所有活动 Survey中必须是唯一的。 In SQL terms, this should always return 0..1 rows: 用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

I plan on handling this constraint at the application level, but would also like some database integrity to be enforced. 我计划在应用程序级别处理此约束,但也希望强制某些数据库完整性。 What is the best way to do this? 做这个的最好方式是什么? Trigger? 触发? Possible in a constraint? 可能有约束吗?

As you are covering 2 tables there is AFAIK only 2 ways to enforce this. 当您覆盖2个表时,只有AFAIK可以执行2种方法。

  1. Trigger as you suggested. 按照您的建议进行触发。
  2. Indexed view with unique constraint accross the 3 columns. 3列中具有唯一约束的索引视图。

As far as reliability is concerned I would go for the Indexed view but the only downside is that it will be difficult to understand by third parties. 就可靠性而言,我会选择索引的观点,但是唯一的缺点是第三方将很难理解。

It is possible to add a constraint that is implemented in a UDF like this: 可以添加在UDF中实现的约束,如下所示:

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

Where complexConstraintFct would be a function containing a query on other tables. 其中complexConstraintFct是一个包含对其他表的查询的函数。 However this approach has some issues as check constraints were designed to be evaluated on a single row at a time but updates can affect more that one row at a time. 但是,这种方法存在一些问题,因为检查约束被设计为一次在单个行上进行评估,但是更新一次可以影响多于一行。

So, the bottom line is: stick with triggers . 因此,最重要的是: 坚持使用触发器

Assuming you are using stored procedures to perform DML operations, you could add a guard clause to the SP that adds answers to surveys to check for the existence of an equivalent answer. 假设您正在使用存储过程执行DML操作,则可以在SP中添加一个保护子句,该子句向调查中添加答案以检查是否存在等效答案。 You could then either throw an exception or return a status code to indicate that the answer could not be added. 然后,您可以引发异常或返回状态代码以指示无法添加答案。

You can't do it at the row level (eg CHECK constraint) so you have to have something that can view all rows 您不能在行级别执行此操作(例如,CHECK约束),因此必须具有可以查看所有行的内容

A trigger can send "nice" messages, but they run after the DML statement. 触发器可以发送“不错的”消息,但是它们在DML语句之后运行。 You have fine control over processing. 您可以很好地控制处理。

An indexed view prevents the DML statement, but it gives a technical error message. 索引视图可以防止DML语句,但是会给出技术错误消息。 It's an extra object and indexes to maintain. 这是一个额外的对象要维护的索引

I think what you're saying is that for any active question, the tuple (surveyDomain, surveyQuestion, surveyAnswer) must be unique? 我认为您的意思是,对于任何活动问题,元组(surveyDomain,surveyQuestion,surveyAnswer)必须是唯一的?

Or in other words, survey:surveyanswer is 1:1 if the survey is active, even though survey:surveyanswer is set up to be 1:many. 换句话说,即使问卷调查处于活动状态,但问卷调查:调查答案仍为1:1,即使将问卷调查:调查答案设置为1:很多。

If so, the answer is to change your table structure. 如果是这样,答案是更改您的表结构。 Adding a nullable activeAnswerId column to survey will effectively make the relation 1:1; 向调查添加可为空的activeAnswerId列将有效地使关系1:1; your existing constraint unique SurveyId (or unique SurveyId, SurvetDomainId) will suffice to enforce uniqueness. 您现有的约束唯一的SurveyId(或唯一的SurveyId,SurvetDomainId)足以实施唯一性。

Indeed, unless I'm misunderstanding, I'm surprised that Survey has a Question column; 确实,除非我有误解,否则我对Survey的“问题”列感到惊讶; I'd expect Survey:Question to be 1:many (a survey has many questions) or even many:many, if a question can show up on more than one survey. 如果一个问题可以出现在多个调查中,我希望Survey:Question为1:很多(一个调查有很多问题),甚至很多:很多。

More generally, I suspect the reason that figuring out how to enforce the constraint is difficult and requires "heroics" like triggers or user defined functions, is a symptom of a schema that doesn't accurately model your problem domain. 更笼统地说,我怀疑弄清楚如何强制执行约束是困难的,并且需要触发器或用户定义的函数之类的“英雄”之类的原因是架构无法对问题域进行准确建模的症状。

OP comments: OP评论:

no, you're missing it. 不,您想念它。 Survey:Answer is 1:n. 调查:答案为1:n。 "Question" is the survey question – Tuple would be (SurveyDomain.SurveyDomainId, Survey.Answer) “问题”是调查问题–元组将是(SurveyDomain.SurveyDomainId,Survey.Answer)

You mean that for every domain, there's at most one answer? 您的意思是,对于每个域,最多只有一个答案? Again, looking at your schema, it's misleading at best. 同样,查看您的架构,这充其量是一种误导。 A SurveyDomain has many Surveys (each of which has a Question column) and a Survey has many Answers? SurveyDomain有很多调查(每个调查都有一个“问题”列),而调查有很多答案? ( Schema ) 架构

But if the Survey's active bit is set, there should be only one Answer? 但是,如果设置了调查的活动位,则应该只有一个答案?

Is Survey a misnomer for Question? Survey是对问题的误称吗?

It's really not clear what you're trying to model. 确实不清楚您要建模的内容。

Again, if it's hard to add a constraint, that suggests that your model doesn't work. 同样,如果很难添加约束,则表明您的模型不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM