代码之家  ›  专栏  ›  技术社区  ›  LBushkin

SQL Server中的可延迟约束

  •  32
  • LBushkin  · 技术社区  · 16 年前

    SQL Server的任何版本都支持可延迟约束(DC)吗?

    从8.0版开始, Oracle has supported deferrable constraints -只在提交语句组时计算的约束,而不是在插入或更新单个表时计算的约束。可延迟约束不同于仅禁用/启用约束,因为这些约束仍处于活动状态-稍后才对其进行评估(提交批处理时)。

    DC的好处是,它们允许对个别可能非法的更新进行评估,从而累积地导致有效的结束状态。一个例子是在两行之间的表中创建循环引用,其中每一行需要一个值。没有单独的insert语句可以传递约束-但是组可以。

    为了阐明我的目标,我希望将C中的ORM实现移植到sqlserver—不幸的是,该实现依赖于Oracle DC来避免计算行之间的插入/更新/删除顺序。

    7 回复  |  直到 7 年前
        1
  •  10
  •   A-K    16 年前

    到目前为止,SQL Server不支持它们。你要解决的问题是什么?

        2
  •  22
  •   Mirko Klemm    15 年前

    OT:有很多事情SQL Server不支持,但在企业环境中是有意义的:

    • 这里提到的可延迟约束
    • 火星:你为什么要为完全自然的东西设定一个选项?
    • 级联删除约束:对于给定的级联删除约束,SQL Server只允许一个级联路径。同样,我不明白为什么不应该允许它通过多个可能的路径在删除时级联:最后,当它真正被执行时,实际上只有一个路径被使用,那么为什么要这样做呢?
    • 防止单个ADO.NET连接上的并行事务。
    • 强制执行在此事务中要执行事务的连接上执行的每个命令。
    • 创建唯一索引时,空值被视为实际值,并且只允许在索引中出现一次。然而,SQL将空值定义为“未知值”的概念表明,在创建索引时,空值将被完全忽略…

    所有这些小东西都构成了许多引用完整性和事务性特性,您可以从全尺寸的RDBMS中期望这些特性在SQL Server中几乎是无用的。例如,由于不支持可延迟的约束,因此将“事务”作为外部一致的工作单元的概念被部分否定,唯一可行的解决方案(除了一些肮脏的解决方案)就是根本不定义引用完整性约束。我希望,事务的自然行为是,您可以按照自己喜欢的操作方式和顺序在事务内部工作,并且系统将确保在提交事务时它是一致的。 类似的问题也来自于限制,即带有on-delete级联的引用完整性约束只能以只有一个约束才能导致对象的级联删除的方式定义。这真的不适合大多数现实场景。

        3
  •  3
  •   Matthew Jones    16 年前

    显然不是。

    我发现大约五篇不同的博客文章都说sqlserver(在不同版本中)不支持可推迟的约束。

    另一方面,我还发现了一个帖子,试图通过使用 "persisted computed columns," (滚动到最后一个条目),但是 买者弃权

        4
  •  3
  •   onedaywhen    16 年前

    听起来您的问题是,SQL不支持什么日期,而Darwin称之为“多重分配”。标准SQL对此的响应是“可延迟约束”,SQL Server不支持这种约束。SQL Server FK或CHECK约束可以标记为NOCHECK,但不完全相同。有关更多详细信息,请参阅msdn: ALTER TABLE (Transact-SQL) .

        5
  •  1
  •   Mirko Klemm    14 年前

    如果您有自己的ORM层,解决问题的一个方法是通过ORM层的逻辑将对象更新与引用更新分开。 然后,您的ORM将根据您的客户端更改集,分几个步骤处理事务:

    1. 删除由更改集定义为要删除的所有外键引用,即将相应的外键列设置为空,或者,对于使用映射表的关系,根据需要从映射表中删除条目。
    2. 删除更改集定义为“已删除”的所有对象
    3. 在更改集中创建所有新对象,但尚未设置外键列
    4. 更新更改集中任何更新对象的所有“基元”值更改,即不更新外键列
    5. 按照更改集中的定义设置外键列值。
    6. 为基于表的映射关系添加映射表映射
    7. 提交

    这应该解决您的问题,因为所有引用的对象在任何时候都存在一个外键值…

        6
  •  1
  •   bitterman0    8 年前

    有一种方法可以解决丢失的延迟约束强制 在一定条件下 (截至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);
    

    其中类型是代理项的某个合适的数据类型。假设代理键的值由RDBMS在插入操作(即标识)期间分配。

    用例是保留nextid=空的实体t的“最新”版本,并通过维护单个链接列表t.nextid->t.id来存储以前的版本。

    显然,给定的模式会受到延迟约束问题的影响,因为新的“最新”版本的插入必须先于旧的“最新”版本的更新,在此期间,数据库中将有两个具有相同nextid值的记录。

    现在,如果:

    主键的数据类型不必是数字,可以预先计算(即uniqueidentifier),然后使用merge语句避免延迟约束问题,如:

    DECLARE TABLE @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语句在检查约束之前完成了所有数据操作。

        7
  •  0
  •   Stephen Rauch Afsar Ali    7 年前

    你可以用这个方法

    ALTER TABLE your_table NOCHECK CONSTRAINT your_constraint
    

    你行动

    ALTER TABLE your_table WITH CHECK CHECK CONSTRAINT ALL