【问题标题】:Does SQL Server allow constraint violations in a transaction as long as it's not committed yet?只要尚未提交,SQL Server 是否允许在事务中违反约束?
【发布时间】:2011-05-12 07:31:32
【问题描述】:

只要事务尚未提交,SQL Server 是否允许在事务中违反约束(即延迟约束)?

我有一个正在运行的、未提交的事务,当这个事务正在运行时,我将更改我的数据,以使其违反某些约束(例如具有重复的主键)。当我提交事务时,数据将处于一致、有效的状态。这通常在 SQL 中,特别是在 MS SQL Server 中允许吗?

【问题讨论】:

    标签: sql sql-server transactions constraints


    【解决方案1】:

    不,对不起。 SQL Server 不允许事务中的延迟约束。它存在于 SQL Server 6.5 中,但在 SQL Server 2000 中被删除:

    SET DISABLE_DEF_CNST_CHK ON
    

    每个单独的语句必须一致等,无论它是否在事务中

    一些 RDBMS 确实允许这样做(例如 Oracle、Postgres、Interbase)

    连接

    有一个Microsoft Connect request,创建于 2006 年,要求提供此功能:

    将外键约束检查推迟到事务提交的选项

    在各种“鸡和蛋”场景中,最好将参照完整性约束的检查推迟到事务的提交时间。

    允许将参照完整性约束检查推迟到事务的提交时间(作为一个选项)。建议在 BEGIN TRANSACTION 上提供一个选项来指定这一点。

    微软的最后一次回应是在十年前:

    由 Sameer [MSFT] 于 2006 年 10 月 13 日下午 1:35 发布

    你好,格雷格,

    感谢您的反馈。我们已经意识到这一点,并正在研究它以供将来发布。

    Sameer Verkhedkar
    SQL 引擎
    [微软]

    微软代表“走开”

    SQL-92 定义了它

    该功能在July 1992 with SQL-92 中定义。一个示例语法是:

    BEGIN TRANSACTION
       SET CONSTRAINTS ALL DEFERRED --applies only to the current transaction
    
       INSERT Customers ...
       INSERT Orders ...
       UPDATE Customers ... --add the thing we were missing
    
    COMMIT TRANSACTION
    

    【讨论】:

    • 完成图片:PostgreSQL 也允许延迟约束。
    • 而且 Interbase 也允许这样做......但是在这个主题上,使用 MSSQL Server 我在随机同步功能/特性中的 FK 检查有同样的问题(通过自定义 API 定期传输一些表更改).. . 最后得到了要插入/更新/删除的表的优先级列表,所以我有正确的序列。
    • 我不清楚这个答案。 'SET DISABLE_DEF_CNST_CHK ON' 是否让您获得所需的行为?如果是这样,你怎么能通过 C# 调用来运行这样的命令?
    • @DannyEllisJr。它不再存在,因为 SQL Server 2000 在 28 年前发布......
    【解决方案2】:

    您可以在运行事务时禁用约束,然后在完成后重新启用它们。

    ALTER TABLE mytable NOCHECK CONSTRAINT myconstraint
    
    --... RUN TRANSACTION
    
    ALTER TABLE mytable WITH CHECK CHECK CONTRAINT ALL
    

    警告:这将影响所有连接。

    【讨论】:

    • 这不会影响所有连接,而不仅仅是您自己的,因此另一个连接可能会在您的事务运行时违反约束,并阻止提交发生?
    • 是的。您还可以锁定整个表以防止这种情况发生。
    • 不过,唯一的问题是,如果我的进程崩溃或异常结束,我不能保证约束会重新打开。当服务器看到我的连接丢失时,事务将被回滚,但不重置约束是个问题......
    • 这不是唯一的问题:如果在此期间另一个事务提交了不一致的修改,您也会遇到麻烦。我还建议性能可能很差。
    • 这是一个危险的建议。虽然您正在运行的更新可能只需要几秒钟,但再次启用受影响的约束可能需要几个小时。因此,您有一个数据库对于 OLTP 来说基本上是离线的(因为您 - 希望 - 持有该表的排他锁)几个小时,而您只想将五行插入两个表中。
    【解决方案3】:

    如果必须(例如从导入文件中清理数据的流程),则将中间数据放入临时表或表变量或暂存表中,然后仅对具有约束的真实表执行操作清理它并使数据正确。

    【讨论】:

    • 我投了反对票,因为您的建议仅适用于 CHECK 约束 - 而不是 FOREIGN KEY 约束,这是真正令人头疼的地方(例如 1:1 关系、自引用表、循环图数据库、多态表、表中的子类等)。
    【解决方案4】:

    SQL Server 没有延迟约束选项。但在某些情况下,您可以使用支持忽略约束而不会出现禁用问题的批量插入。有关更多信息,您可以查看以下链接:

    那么在提交事务之前,你将不得不手动检查整个表的约束。

    【讨论】:

      猜你喜欢
      • 2020-07-03
      • 1970-01-01
      • 2016-07-29
      • 2021-04-11
      • 2013-02-26
      • 1970-01-01
      • 1970-01-01
      • 2018-04-27
      • 1970-01-01
      相关资源
      最近更新 更多