Dans SQL Server, comment appliquer des noms de petits-enfants uniques dans un model de hiérarchie?

Modèle: les commerçants ont un à plusieurs clients et les clients ont un à plusieurs counts. Les counts ont des noms. Les trois tables ont des identifiants uniques pour chaque ligne.

Contrainte: Pour un marchand donné, les noms de count doivent être uniques.

Comment appliquons-nous cette contrainte dans un schéma de database SQL Server?

Voici quelques idées que nous avons considérées:

  • Nous pourrions append MerchantId à la table Account et créer une contrainte unique, mais il s'agit d'une colonne redondante à conserver étant donné que CustomerId est déjà présent. Nous devons nous assurer que la combinaison de MerchantId et CustomerId est cohérente, donc nous ferions en sorte que la key étrangère entre Account et Customer inclue les deux colonnes, même si CustomerId est déjà un identifiant unique.
  • Nous pourrions append une contrainte de vérification à la table Compte et utiliser une fonction UDF pour vérifier la règle de contrainte. Mais alors, un client pourrait convenir à un autre marchand, et la contrainte de vérification sur le count ne serait pas vérifiée. Nous devrons donc append une autre contrainte sur la table Customer, ce qui nous donne l'printing de ne pas le faire correctement, d'autant plus que le vrai model est plus complexe que décrit ici.
  • Nous pourrions appliquer la contrainte via des triggersurs, mais cela ne semble pas améliorer les problèmes d'utilisation des contraintes de vérification.

Peut-être que la meilleure idée d'une solution est de créer une vue joignant les 3 tables et de créer un index unique sur cette vue. Ce serait une vue indexée . Lorsque vous indexez une vue, elle est conservée comme une table normale, mais elle est mise à jour automagiquement par le moteur de database dans le cadre des commands DML classiques.

Il y a beaucoup d'exigences et de ressortingctions sur ce que vous pouvez et ne pouvez pas faire, ce sont dans les documents auxquels je suis lié ci-dessus, mais je pense que vous pouvez vous en sortir.

Le code irait comme ceci:

CREATE VIEW dbo.MerchantAccounts WITH SCHEMABINDING AS SELECT m.MerchantKey, a.AccountKey, a.Name FROM dbo.Accounts a INNER JOIN dbo.Customers c ON a.CustomerKey = c.CustomerKey INNER JOIN dbo.Merchants m ON c.MerchantKey = m.MerchantKey; GO CREATE UNIQUE CLUSTERED INDEX IX_MerchantKey_AccountName ON dbo.MerchantAccounts (MerchantKey, Name); GO 

J'ai inclus 3 colonnes dans la vue mais seulement 2 font partie de l'index cluster unique. Donc, vous ne devez pas avoir dupliqué MarchantKey,AccountName pour commencer, et après cela, le moteur de database assurera cela pour vous.

Vous n'avez pas besoin de changer votre table et vos relations tant que vous ne violez pas les exigences.

Vous pouvez inclure plus de colonnes que les seules colonnes de key dans votre vue d'index, ce qui peut améliorer les performances de certaines requêtes. C'est à toi de voir. SELECT * FROM dbo.MerchantAccounts simplement que le résultat de la vue (l'équivalent de SELECT * FROM dbo.MerchantAccounts ) sera conservé sur votre database et occupera de l'espace. Ainsi, plus vous ajoutez de colonnes, plus la vue est grande et plus elle est chère pour la maintenir à jour.