只要事务尚未提交,SQL Server 是否允许事务中违反约束?

发布于 2024-11-07 05:33:18 字数 188 浏览 0 评论 0原文

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

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

Does SQL Server allow constraint violations (i.e. deferred constraints) in a transaction as long as the transaction has not been committed yet?

I have a running, uncommitted transaction and while this transaction is running, I will change my data so that it will violate some constraints (like having duplicate primary keys for example). When I commit the transaction, the data will be in consistent, valid state. Is this generally allowed in SQL and specifically in MS SQL Server?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

清欢 2024-11-14 05:33:19

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

SET DISABLE_DEF_CNST_CHK ON

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

(例如 Oracle、Postgres、Interbase

一些 RDBMS 确实允许这样做

) href="https://connect.microsoft.com/SQLServer/feedback/details/124728/option-to-defer-foreign-key-constraint-checking-until-transaction-commit" rel="noreferrer">Microsoft Connect 请求,创建于 2006 年,请求此功能:

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

存在各种“先有鸡还是先有蛋”的场景,需要将参照完整性约束的检查推迟到事务的提交时间。

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

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

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

你好格雷格,

感谢您的反馈。我们已意识到这一点,并会在未来的版本中进行研究。

萨米尔·维尔赫德卡
SQL引擎
[微软金融时报]

这是微软对“走开”的说法。

SQL-92 定义了

该功能于 1992 年 7 月通过 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

No, sorry. SQL Server does not allow deferred contraints in a transaction. It was present in SQL Server 6.5, but removed in SQL Server 2000:

SET DISABLE_DEF_CNST_CHK ON

Each individual statement must be consistent etc, regardless of whether it is in a transaction

Some RDBMS do allow this (e.g. Oracle, Postgres, Interbase)

Connect

There is a Microsoft Connect request, created in 2006, asking for this feature:

Option to defer foreign key constraint checking until transaction commit

There are various "chicken and egg" scenarios where it would be desirable to defer the checking of referential integrity constraints until commit time on a transaction.

Allow deferring of referential integrity constraint checking until commit time on a transaction (as an option). Suggest providing an option on BEGIN TRANSACTION that specifies this.

The last response from Microsoft came a decade ago:

Posted by Sameer [MSFT] on 10/13/2006 at 1:35 PM

Hello Greg,

Thanks for the feedback. We are aware of this and looking into it for a future release.

Sameer Verkhedkar
SQL Engine
[MSFT]

Which is Microsoft speak for "go away".

SQL-92 defines it

The feature was defined in July 1992 with SQL-92. An example syntax would be:

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
耶耶耶 2024-11-14 05:33:19

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

ALTER TABLE mytable NOCHECK CONSTRAINT myconstraint

--... RUN TRANSACTION

ALTER TABLE mytable WITH CHECK CHECK CONTRAINT ALL

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

You can disable your constraints while running your transaction, and then reenabling them when you are done.

ALTER TABLE mytable NOCHECK CONSTRAINT myconstraint

--... RUN TRANSACTION

ALTER TABLE mytable WITH CHECK CHECK CONTRAINT ALL

Warning: This will affect all connections.

尐籹人 2024-11-14 05:33:19

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

If you must (such as a Process to cleanse data from an import file), then put the intermediate data into Temp tables or table variables or staging tables and then only do the actions to the real tables with the constraints after you have cleansed it and made the data correct.

2024-11-14 05:33:19

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

然后在提交事务之前,您必须手动检查整个表的约束。

SQL Server does not have deferred contraints option. But in some cases you can use Bulk Insert that supports ignoring constraints without problems of disabling. For more information you can see these links:

Then just before committing transaction, you will have to check the constraints on the whole table manually.

各空 2024-11-14 05:33:19

您也可以使用合并命令。它们一起解决,绕过约束中间状态。这是一个例子。在插入之前,John 的 pk id=1,Marta 的 pk id=2。名字和姓氏是唯一的。合并命令开关放置在 MERGE 之后,John 的 PK id=2 且 Marta id=1。使用普通更新命令无法切换 Marta 和 Joe 名称。

CREATE TABLE dbo.People
(
    Id        int          NOT NULL IDENTITY,
    FirstName NVARCHAR(50) NOT NULL,
    LastName  NVARCHAR(50) NOT NULL,
    CONSTRAINT UQ_People UNIQUE (FirstName, LastName)
);

--SELECT * FROM People;
--TRUNCATE TABLE People;

INSERT INTO People (FirstName, LastName)
VALUES
    (N'John', N'Doe'),
    (N'Marta', N'Smith'),
    (N'Julius','Manfred');

MERGE dbo.People AS P
USING (
      SELECT 1 AS Id, 'Marta' AS FirstName, 'Smith' AS LastName
       UNION
      SELECT 2, 'John', 'Doe'
       UNION
      SELECT 8, 'Martin', 'Berg') AS Flip
ON P.Id = Flip.Id
WHEN MATCHED AND (P.FirstName <> Flip.FirstName OR P.LastName <> Flip.LastName) THEN
    UPDATE
       SET P.FirstName = Flip.FirstName,
           P.LastName  = Flip.LastName
WHEN NOT MATCHED BY TARGET THEN
    INSERT
    (FirstName,
     LastName)
    VALUES
        (Flip.FirstName,
         Flip.LastName)
WHEN NOT MATCHED BY SOURCE THEN DELETE
    OUTPUT INSERTED.*, DELETED.*, $action;

SELECT *
  FROM People;

ALTERNATIVE you can use Merge commands. They resolve together, bypassing the constraint intermediary state. Here is an example. Before insert, John has pk id=1, Marta has pk id=2. Firstname and lastname are unique. The Merge command switch places and after the MERGE John has PK id=2 and Marta id=1. Switching Marta and Joe names are not possible with normal update commands.

CREATE TABLE dbo.People
(
    Id        int          NOT NULL IDENTITY,
    FirstName NVARCHAR(50) NOT NULL,
    LastName  NVARCHAR(50) NOT NULL,
    CONSTRAINT UQ_People UNIQUE (FirstName, LastName)
);

--SELECT * FROM People;
--TRUNCATE TABLE People;

INSERT INTO People (FirstName, LastName)
VALUES
    (N'John', N'Doe'),
    (N'Marta', N'Smith'),
    (N'Julius','Manfred');

MERGE dbo.People AS P
USING (
      SELECT 1 AS Id, 'Marta' AS FirstName, 'Smith' AS LastName
       UNION
      SELECT 2, 'John', 'Doe'
       UNION
      SELECT 8, 'Martin', 'Berg') AS Flip
ON P.Id = Flip.Id
WHEN MATCHED AND (P.FirstName <> Flip.FirstName OR P.LastName <> Flip.LastName) THEN
    UPDATE
       SET P.FirstName = Flip.FirstName,
           P.LastName  = Flip.LastName
WHEN NOT MATCHED BY TARGET THEN
    INSERT
    (FirstName,
     LastName)
    VALUES
        (Flip.FirstName,
         Flip.LastName)
WHEN NOT MATCHED BY SOURCE THEN DELETE
    OUTPUT INSERTED.*, DELETED.*, $action;

SELECT *
  FROM People;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文