Wie erstelle ich eine Tabellenbedingung doppelte Werte über zwei Spalten zu verhindern?

StackOverflow https://stackoverflow.com/questions/626609

  •  06-07-2019
  •  | 
  •  

Frage

Ich habe die folgende Tabelle:

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]

Ein Teil der Daten in der Tabelle sieht aus wie etwas so aus:

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

Ich mag eine Einschränkung hinzufügen, um sicherzustellen, dass niemand ergänzt oder aktualisiert einen Datensatz IsActive = 1, haben, wenn es bereits ein Rekord für die EntityIdNmb ist, wo IsActive = 1 ist.

Wie kann ich das tun?

War es hilfreich?

Lösung

Wenn Sie SQLServer verwenden Sie können einen gruppierten indizierte Sicht erstellen.

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)

Dies stellt sicher, es gibt nur eine EntityIdNmb in Ihrer Tabelle mit IsActive = 1 ist.

Andere Tipps

Klingt wie Sie einen Trigger implementieren müssen (vorausgesetzt, Ihr db Produkt unterstützt). Wenn Sie nur einen aktiven und einen inaktiven Eintrag wollen, wird ein eindeutiger Index arbeiten. Andernfalls müssen Sie irgendeine Art von benutzerdefinierter Einschränkung oder einen Trigger schreiben. (Wahrscheinlich 2 - einen für Einsätze, ein für Updates), die dafür sorgt, dass Sie nicht über 2 Datensätze mit derselben ID, wo beide aktiv sind

Wenn Sie mit MSSQL (ich glaube, das ist, was Ihre Syntax aussieht), Erstellen Sie eine Ansicht, das nur die Zeilen mit IsActive = 1, dann einen eindeutigen Index in der Ansicht auf EntityIdNmb setzen.

In PostgreSQL, die ich mehr mit letzter Zeit gearbeitet haben, können Sie einen Teilindex erstellen: http://www.postgresql.org/docs/8.3/interactive/ Indizes-partial.html

Die Sache der Auslöser mit dem Schreiben zu entscheiden, ob Sie den Datensatz ablehnen mögen, den Wert auf 0 geändert wird anstelle einem oder den alten Rekord auf Null aktualisieren und diese lassen, als einer aufsteht. Wenn Sie den Datensatz mit dem Wert von 1 löschen, brauchen Sie einen anderen Datensatz wechseln die aktive zu sein, wie zu tun wählen Sie welche? Sobald Sie definieren können waht Sie innerhalb des Triggers tun wollen, können wir Ihnen helfen, den Prozess besser zu gestalten.

Wir machen die letzten beiden Schritte eine beliebige Adresse der Hauptpostadresse in unserer Datenbank zu machen. Unsere Geschäftsregel ist eine und nur eine Adresse kann das Haupt sein, und wenn es irgendwelche Adressen muss man als Haupt ein markiert werden. Der Schlüssel zu dieser Art von Trigger ist zu bedenken, dass Einsätze / Aktuelles / Löschungen in Chargen auftreten kann (auch wenn dies ist die nicht die Norm) und um sicherzustellen, dass der Auslöser arbeitet in einem Satz basierte. Als ich hier ankam, implementiert unsere mehrreihigen Verarbeitung durch einen Cursor, der eine schlechte Sache geworden, als ich 200.000 addresss in einem Import aktualisieren musste. (Hinweis für die unerfahrenen - nicht immer einen Cursor in einem Trigger verwenden)

Was werden die inaktiven Datensätze verwendet werden? Sind sie nicht benutzt und einfach da Spur von vorher aktiven Aufzeichnungen zu halten? Wenn ja, wäre es möglich, die Daten in mehreren Tabellen aufgeteilt? So etwas wie ...

EntityAttributeRelship (IDNmb, EntityIDNmb, AttributeIDNmb)

EntityAttributeRelshipHistory (IDNmb, EntityIDNmb, AttributeIDNmb)

Wenn es in der EntityAttributeRelship Tabelle ist, ist es aktiv. Wenn es in der Geschichte Tabelle ist dann wurde es zu einem bestimmten Zeitpunkt aktiviert und deaktiviert, da wurde?

Wenn Sie alles tun müssen, in einer Tabelle I mit todd.run Vorschlag der Verwendung eines Trigger gehen würde.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top