2017-04-06 1 views
0

Ich habe eine kleine Tabelle (Code unten) mit PageKey (int), SendNotification (Bit) mit 5 möglichen PageKeys im Moment.Statt Update Trigger auf Bit Spalte

Die Anforderung besteht darin, nicht mehr als 1 Flag (SendNotification) gleichzeitig aktiv zu haben. Daher möchte ich einen Trigger erstellen, der das Flag nicht auf True setzt, wenn bereits ein anderer pageKey mit aktivem Flag vorhanden ist.

Ich schrieb den folgenden Trigger, aber es scheint nicht zu funktionieren. Wenn Sie weitere (bessere) Lösungen in SQL Server 2012 haben, würde ich das ebenfalls begrüßen.

CREATE TRIGGER trg_Notification_Flag 
ON dbo.t_Notification_Flag 
INSTEAD OF UPDATE 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @countOfExistingFlags INT; 
    DECLARE @PageKey INT; 

    SELECT @countOfExistingFlags = COUNT(*) 
    FROM dbo.t_Notification_Flag 
    WHERE SendNotification = 1; 

    SELECT @PageKey = inserted.PageKey 
    FROM inserted; 

    IF @countOfExistingFlags > 1 
    BEGIN 
     PRINT 'There is an existing active flag. No changes has been done.'; 
     ROLLBACK TRANSACTION; 
    END; 
    ELSE 
    BEGIN 
     UPDATE dbo.t_Notification_Flag 
     SET SendNotification = 1 
     WHERE PageKey = @PageKey; 
    END; 
END; 
GO 

Tabelle ist:

CREATE TABLE [dbo].[t_Notification_Flag] 
(
    [PageKey] [int] NOT NULL, 
    [SendNotification] [bit] NOT NULL, 
    [NotificationMessage] [nvarchar](100) NOT NULL, 
    [NotificationHeader] [nvarchar](50) NULL, 
    [Country_Key] [int] NULL 
) ON [PRIMARY] 
+3

Ihr Auslöser hat einen großen Fehler. Es wird davon ausgegangen, dass nur 1 Wert eingefügt wurde. Auslöser werden einmal pro Vorgang ausgelöst. Außerdem sollten Sie vorsichtig sein, wenn Sie einen Rollback innerhalb Ihres Triggers ausführen. Dies kann zu einer Anwendung führen, die eine Transaktion hat. –

Antwort

2

Sie können Ihr Ziel ohne Trigger erreichen - aber nur mit gefilterten eindeutigen Index.

Etwas wie:

create table dbo.#Temp (PageKey int, Send_Notification bit) 
create unique index IX_Temp on dbo.#temp(Send_Notification) where Send_Notification = 1 

Dies wird nicht zulassen, dass Ihre Tabelle mehr als einen Datensatz Send_Notification = 1 mit haben, wenn Sie also Send_Notification Flagge für einige Rekord einstellen müssen - Sie werden es löschen müssen zuerst der Datensatz, für den dieses Flag derzeit gesetzt ist.

+0

In welcher Version von SQL Server wurden gefilterte Indizes verfügbar? –

+1

@TabAlleman soweit ich mich erinnere, sind sie mindestens in 2008 Version –

+0

@AndyKorneev vielen Dank, diese Lösung ist viel eleganter und funktioniert der Zweck perfekt. Keine Notwendigkeit, das Rad neu zu erfinden ;-) – KathyBlue

1

Ich würde keinen Trigger überhaupt für diese. Stattdessen würde ich einen CHECK CONSTRAINT verwenden, der eine UDF überprüft, die true zurückgibt, wenn keine anderen aktiven Flags vorhanden sind, und false, wenn es solche gibt.