任何版本的SQL Server是否支持可延迟约束(DC)?
从版本8.0开始,Oracle has supported deferrable constraints - 仅在提交语句组时评估的约束,而不是在插入或更新单个表时。可延迟约束不仅仅是禁用/启用约束,因为约束仍处于活动状态 - 它们只是稍后进行评估(批量提交时)。
DC的好处是它们允许评估单独非法的更新,这些更新累积地导致有效的最终状态。一个示例是在两行之间的表中创建循环引用,其中每行需要存在一个值。没有单独的插入语句会通过约束 - 但组可以。
为了阐明我的目标,我希望将C#中的ORM实现移植到SQLServer - 遗憾的是,实现依赖于Oracle DC来避免在行之间计算插入/更新/删除命令。
答案 0 :(得分:23)
所有这些小东西都会使您在SQL Server中几乎无用的全尺寸RDBMS所具有的许多参照完整性和事务性功能。例如,由于不支持可延迟约束,因此“事务”作为外部一致工作单元的概念被部分否定,唯一可行的解决方案 - 除了一些肮脏的解决方法 - 根本就没有定义参照完整性约束。我希望,事务的自然行为是你可以按照你喜欢的操作方式和顺序在其中工作,系统将确保它在你提交它时是一致的。 限制产生了类似的问题,即ON DELETE CASCADE的参照完整性约束只能以只有一个约束可以导致对象的级联删除的方式定义。这真的不适合大多数现实场景。
答案 1 :(得分:11)
到目前为止,SQL Server不支持它们。你正在解决的问题是什么?
答案 2 :(得分:3)
显然不是。
我发现大约有五篇不同的博客帖子都说SQLServer(各种版本)不支持Deferrable Constraints。
另一方面,我还发现了一篇试图通过使用"persisted computed columns,"(滚动到最后一个条目)来模仿此功能的帖子,但是告诫者
答案 3 :(得分:3)
听起来你遇到的问题是SQL不支持Date和Darwen所谓的“多重赋值”。标准SQL对此的响应是“延迟约束”,SQL Server不支持。可以使用NOCHECK标记SQL Server FK或CHECK约束,但它不完全相同。有关详细信息,请参阅MSDN:ALTER TABLE (Transact-SQL)。
答案 4 :(得分:2)
有一种方法可以在某些条件下解决丢失的延迟约束强制 (截至2017年1月,SQL Server中不支持延迟约束)。请考虑以下数据库模式:
免责声明:架构的质量或用例不适用于此处的争论,它是作为解决方法的基本示例
CREATE TABLE T (Id TYPE NOT NULL PRIMARY KEY, NextId TYPE NOT NULL);
ALTER TABLE T WITH CHECK ADD CONSTRAINT FK_T2T
FOREIGN KEY (NextId) REFERENCES T (Id);
CREATE UNIQUE NONCLUSTERED INDEX UC_T ON T (NextId);
其中TYPE是代理键的某种合适的数据类型。假设代理键的值由INSERT操作期间的RDBMS分配(即IDENTITY)。
用例是保持"最新的"具有NextId = NULL的实体T的版本,并通过维护单链表T.NextId - >来存储先前版本。 T.Id。
显然,给定的模式受延迟约束问题的影响,因为插入了新的 - "最新的"版本必须在更新旧版本之前 - "最新版本"在此期间,数据库中将有两条具有相同NextId值的记录。
现在,如果:
主键的数据类型不必是数字,并且可以提前计算(即UNIQUEIDENTIFIER),然后使用MERGE语句回避延迟约束问题,如下所示:
DECLARE @MergeTable TABLE (Id UNIQUEIDENTIFIER);
DECLARE @NewLatestVersion UNIQUEIDENTIFIER = NEWID();
INSERT INTO @MergeTable (Id) VALUES (@NewLatestVersion);
INSERT INTO @MergeTable (Id) VALUES (@OldLatestVersion);
MERGE INTO T
USING @MergeTable m ON T.Id = m.Id
WHEN MATCHED THEN UPDATE SET T.NextId = @NewLatestVersion
WHEN NOT MATCHED THEN INSERT (Id) VALUES (@NewLatestVersion);
显然,MERGE语句在检查约束之前完成所有数据操作。
答案 5 :(得分:1)
如果您有自己的ORM层,问题的一个解决方案可能是通过ORM层的逻辑将对象更新与参考更新分开。 然后,您的ORM将根据您的客户端更改集在几个步骤中处理事务:
这可以解决您的问题,因为所有引用的对象都可以在任何时候设置外键值...
答案 6 :(得分:0)
您可以使用此方法
<!-- language-all: lang-or-tag-here -->
columns: [{
field: "checkboxDisplay",
title: "checkboxDisplay",
template: "# if ('new' =='new') { # <input id = 'checkIDGrid' type='checkbox' checked=true class=''> # }else{# <span class='oldEventArrow'></span> #} #"
}
你的行动
ALTER TABLE your_table NOCHECK CONSTRAINT your_constraint