我有基于短信的调查应用程序,它接受调查域和答案。
我收到了详细的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
我计划在应用程序级别处理此约束,但也希望强制执行某些数据库完整性。做这个的最好方式是什么?触发?在约束中可能吗?
答案 0 :(得分:2)
当你涉及2个表时,AFAIK只有2种方法来强制执行此操作。
就可靠性而言,我会选择索引视图,但唯一的缺点是第三方难以理解。
答案 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?
调查是否是一个用词不当的问题?
目前还不清楚你想要建模的是什么。
同样,如果添加约束很难,则表明您的模型不起作用。