Contraintes différables dans SQL Server

Toutes les versions de SQL Server prennent-elles en charge les contraintes différables (DC)?

Depuis la version 8.0, Oracle prend en charge les contraintes différables - contraintes qui ne sont évaluées que lorsque vous validez un groupe d'instructions, et non lorsque vous insérez ou mettez à jour des tables individuelles. Les contraintes différables diffèrent des contraintes de désactivation/activation, en ce sens que les contraintes sont toujours actives - elles sont évaluées plus tard (lorsque le lot est validé).

L'avantage de DC est qu'ils permettent aux mises à jour qui individuellement seraient illégales d'être évaluées de manière cumulative dans un état final valide. Un exemple est la création de références circulaires dans une table entre deux lignes où chaque ligne nécessite une valeur pour exister. Aucune instruction insert individuelle ne passerait la contrainte - mais le groupe le peut.

Pour clarifier mon objectif, je cherche à porter une implémentation ORM en C# vers SQLServer-malheureusement, L'implémentation repose sur Oracle DC pour éviter l'informatique insérer/mettre à jour / supprimer des ordres parmi les lignes.

32
demandé sur LBushkin 2009-06-16 00:03:20

7 réponses

JUSQU'à présent, SQL Server ne les prend pas en charge. Quel est le problème que vous résolvez?

10
répondu A-K 2009-06-15 20:25:34

OT: il y a à mon humble avis Pas mal de choses que SQL Server ne supporte pas, mais cela aurait du sens dans un environnement d'entreprise:

  • contraintes Différables comme mentionné ici
  • MARS: juste pourquoi avez-vous besoin de définir une option pour quelque chose de tout à fait naturel?
  • contraintes de suppression en CASCADE: SQL Server n'autorise qu'un seul chemin de cascadation pour une contrainte de suppression en CASCADE donnée. Encore une fois, je ne vois pas de raison pour laquelle il ne devrait pas être autorisé à cascade sur la suppression via plusieurs chemins possibles: à la fin, au moment où il est réellement exécuté, il n'y aura toujours qu'un seul chemin réellement utilisé, alors pourquoi cette restriction?
  • prévention des transactions parallèles sur un ADO.NET connexion.
  • forcer chaque commande exécutée sur une connexion qui a une transaction à exécuter dans cette transaction.
  • lors de la création D'un index UNIQUE, NULL est traité comme s'il s'agissait d'une valeur réelle et n'apparaît qu'une seule fois dans l'index. La notion de SQL de NULL en tant que "valeur inconnue" indiquerait cependant que les valeurs NULL seront complètement ignorées lors de la création de l'index...

Toutes ces petites choses rendent la plupart des fonctionnalités d'intégrité référentielle et transactionnelles que vous attendez d'un SGBDR de taille normale presque inutiles dans SQL Server. Par exemple, puisque les contraintes différables ne sont pas prises en charge, la notion de "transaction" en tant qu'Unité de travail cohérente de l'extérieur est partiellement annulée, la seule solution viable-sauf pour certains sales solutions de contournement-étant de ne pas définir les contraintes d'intégrité référentielle du tout. Je dirais que le comportement naturel d'une opération que vous pouvez travailler à l'intérieur dans la manière et l'ordre des opérations que vous aimez, et le système assurez-vous qu'il est conforme au moment de la commettre. Des problèmes similaires découlent de la restriction, qu'une contrainte d'intégrité référentielle avec ON DELETE CASCADE ne peut être définie que de manière à ce qu'une seule contrainte puisse conduire à la suppression en cascade d'un objet. Cela ne correspond vraiment pas à la plupart des scénarios du monde réel.

21
répondu Mirko Klemm 2010-02-23 13:07:35

Apparemment non.

J'ai trouvé environ cinq articles de blog différents disant tous que SQLServer (dans diverses versions) ne supporte pas les contraintes Différables.

D'autre part, j'ai aussi trouvé un post qui tente d'imiter cette fonctionnalité à l'aide de "colonnes calculées persistantes," (faites défiler jusqu'à la dernière entrée), mais caveat emptor

3
répondu Matthew Jones 2009-06-15 20:26:07

Il semble que le problème que vous avez est que SQL ne supporte pas quelle Date et Darwen appelle 'affectation multiple'. La réponse de SQL Standard à cela était 'contraintes différables', que SQL Server ne prend pas en charge. Une contrainte SQL Server FK ou CHECK peut être marquée avec NOCHECK mais ce n'est pas tout à fait la même chose. Pour plus de détails, consultez MSDN: ALTER TABLE (Transact-SQL).

3
répondu onedaywhen 2009-06-16 09:31:16

Si vous avez votre propre couche ORM, une solution à votre problème pourrait être de séparer object update de reference update par la logique de votre couche ORM. Votre ORM fonctionnerait alors avec des transactions basées sur votre changement côté client défini en plusieurs étapes:

  1. supprimez toutes les références de clés étrangères définies par votre jeu de modifications comme étant supprimées, c'est-à-dire définissez les colonnes de clés étrangères correspondantes sur NULL, ou, pour les relations utilisant des tables de mappage, supprimez les entrées des tables de mappage comme approprié.
  2. Supprimer tous les objets définis comme "supprimés" par vos jeux de modifications
  3. Créez tous les nouveaux objets de votre jeu de modifications, mais Ne définissez pas encore de colonnes de clés étrangères
  4. Mettre à jour toutes les modifications de valeur "primitives" sur les objets mis à jour dans le jeu de modifications, c'est-à-dire ne pas mettre à jour les colonnes de clés étrangères
  5. Définissez les valeurs de colonne de clé étrangère telles que définies dans votre jeu de modifications.
  6. Ajouter des mappages de table de mappage pour les relations basées sur la table de mappage
  7. Commettre

Cela devrait résolvez votre problème, car tous les objets référencés existent à tout moment une valeur de clé étrangère est définie...

1
répondu Mirko Klemm 2011-05-02 10:39:23

Il existe une méthode pour contourner l'application de contrainte différée manquante sous certaines conditions (en janvier 2017, il n'y a pas de prise en charge des contraintes différées dans SQL Server). Considérez le schéma de base de données suivant:

Avertissement: La qualité du schéma, ou les cas d'utilisation, n'est pas un débat ici, il est donné comme un exemple de base pour la solution de contournement

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);

Où TYPE est un type de données approprié pour une clé de substitution. L'hypothèse est que l' la valeur de la clé de substitution est assignée par le SGBDR pendant l'opération D'insertion (C'est-à-dire L'identité).

Le cas d'utilisation est de conserver la "dernière" version de L'entité T avec NextId = NULL, et de stocker les versions précédentes en conservant une liste à lien unique T. NextId- > T.Id.

Évidemment, le schéma donné est soumis au problème de contrainte différée car l'insertion de la nouvelle version-"latest" doit précéder la mise à jour de l'ancienne - "latest" et pendant ce temps il y aura deux enregistrements dans la base de données avec la même valeur NextId.

Maintenant, si:

Le type de données de la clé primaire n'a pas besoin d'être numérique et peut être calculé à l'avance( c'est-à-dire UNIQUEIDENTIFIER), puis le problème de contrainte différée est évité en utilisant L'instruction MERGE, comme ceci:

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);

Apparemment, L'instruction MERGE complète toutes les manipulations de données avant de vérifier les contraintes.

1
répondu bitterman0 2017-01-19 06:07:13

Vous pouvez utiliser cette méthode

ALTER TABLE your_table NOCHECK CONSTRAINT your_constraint

Votre action

ALTER TABLE your_table WITH CHECK CHECK CONSTRAINT ALL
0
répondu Đăng Khoa 2018-04-03 02:31:41