Question

J'ai le tableau suivant:

CREATE TABLE [dbo].[EntityAttributeRelship](
    [IdNmb] [int] IDENTITY(1,1) NOT NULL,
    [EntityIdNmb] [int] NOT NULL,
    [AttributeIdNmb] [int] NOT NULL,
    [IsActive] [bit] NOT NULL CONSTRAINT [DF_EntityAttributeRelship_IsActive]  DEFAULT ((0)),
CONSTRAINT [PK_EntityAttributeRelship] PRIMARY KEY CLUSTERED 
([IdNmb] ASC) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]) ON [PRIMARY]

Une partie des données de la table ressemble à quelque chose comme ceci:

IdNmb    EntityIdNmb    AttributeIdNmb  IsActive
1        22             7               0
2        22             8               0
3        22             9               0
4        22             10              1

Je souhaite ajouter une contrainte pour m'assurer que personne n'ajoute ou ne met à jour un enregistrement avec IsActive = 1, s'il existe déjà un enregistrement pour EntityIdNmb où IsActive = 1.

Comment puis-je faire cela?

Était-ce utile?

La solution

Si vous utilisez SQLServer, vous pouvez créer une vue indexée en cluster.

CREATE VIEW dbo.VIEW_EntityAttributeRelship WITH SCHEMABINDING AS
SELECT EntityIdNmb 
FROM dbo.EntityAttributeRelship
WHERE IsActive = 1
GO

CREATE UNIQUE CLUSTERED INDEX UIX_VIEW_ENTITYATTRIBUTERELSHIP 
  ON dbo.VIEW_EntityAttributeRelship (EntityIdNmb)

Cela garantit qu'il n'y a qu'un seul EntityIdNmb dans votre table avec IsActive = 1.

Autres conseils

On dirait que vous devez implémenter un déclencheur (en supposant que votre produit de base de données le supporte). Si vous ne voulez qu'une entrée active et une entrée inactive, un index unique fonctionnera. Sinon, vous devrez écrire une sorte de contrainte personnalisée ou un déclencheur (probablement 2 - un pour les insertions, un pour les mises à jour) qui garantit que vous n'avez pas 2 enregistrements avec le même identifiant où les deux sont actifs.

Si vous utilisez MSSQL (je pense que c'est ce à quoi ressemble votre syntaxe), créez une vue comprenant uniquement les lignes avec IsActive = 1, puis mettez un index unique sur EntityIdNmb dans la vue.

Dans PostgreSQL, avec lequel j'ai beaucoup travaillé récemment, vous pouvez créer un index partiel: http://www.postgresql.org/docs/8.3/interactive/ indexes-partial.html

Le problème avec l’écriture du déclencheur est de décider si vous voulez rejeter l’enregistrement, changer la valeur à 0 au lieu de un ou mettre à jour l’ancien enregistrement à zéro et laisser l’enregistrement unique. Si vous supprimez l'enregistrement avec la valeur 1, devez-vous changer un autre enregistrement pour qu'il soit actif, comment choisir lequel? Une fois que vous pouvez définir ce que vous voulez faire dans le déclencheur, nous pouvons vous aider à mieux concevoir le processus.

Nous effectuons les deux dernières étapes pour transformer toute adresse en adresse postale principale de notre base de données. Notre règle de gestion est une et une seule adresse peut être la principale et s'il y a des adresses, il faut en indiquer l'adresse principale. La clé de ce type de déclencheur est de garder à l'esprit que les insertions / mises à jour / suppressions peuvent se produire par lots (même si ce n'est pas la norme) et de s'assurer que le déclencheur fonctionne comme un ensemble. Lorsque je suis arrivé ici, nous avons implémenté le traitement sur plusieurs lignes à l'aide d'un curseur, ce qui est devenu une mauvaise chose lorsque j'ai dû mettre à jour 200 000 adresses dans une importation. (Note aux inexpérimentés - n’utilisez jamais de curseur dans un déclencheur!)

À quoi vont servir les enregistrements inactifs? Sont-ils inutilisés et simplement là pour garder trace des enregistrements précédemment actifs? Si oui, serait-il possible de scinder les données en plusieurs tables? Quelque chose comme ...

EntityAttributeRelship (IDNmb, EntityIDNmb, AttributeIDNmb)

EntityAttributeRelshipHistory (IDNmb, EntityIDNmb, AttributeIDNmb)

Si c'est dans la table EntityAttributeRelship, c'est actif. Si cela se trouve dans la table d'historique, il a été activé à un moment donné et a depuis été désactivé?

Si vous avez besoin de tout ce qui se trouve dans une seule table, j'irais de pair avec la suggestion de todd.run d'utiliser un déclencheur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top