Do any versions of SQL Server support deferrable constraints (DC)?
Since about version 8.0, Oracle has supported deferrable constraints - constraints that are only
There's a method to work around the missing deferred constraint enforcement under certain conditions (as of January 2017, there's no support for deferred constraints in SQL Server). Consider the following database schema:
Disclaimer: The quality of the schema, or the use case, is not up for a debate here, it is given as a basic example for the workaround
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);
Where TYPE is some suitable data type for a surrogate key. The assumption is that the value for the surrogate key is assigned by the RDBMS during the INSERT operation (i.e. IDENTITY).
The use case is to keep the "latest" version of the entity T with NextId = NULL, and store the previous versions by maintaining a single-linked list T.NextId -> T.Id.
Obviously, the given schema is subject to the deferred constraint problem because the insert of the new-"latest" version must precede the update of the old-"latest" and during that time there will be two records in the database with the same NextId value.
Now, if:
The data type of the primary key doesn't have to be numeric, and can be calculated in advance (i.e. UNIQUEIDENTIFIER), then the deferred constraint problem is sidestepped using MERGE statement, like so:
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);
Apparently, MERGE statement completes all data manipulations before checking the constraints.