2012-03-31 13 views
1

Ich muss einen Auslöser erstellen, der ausgelöst wird, wenn ein untergeordneter Datensatz (Codes) hinzugefügt, aktualisiert oder gelöscht wird. Der Trigger fügt eine Zeichenfolge aus kommagetrennten Codewerten aus allen untergeordneten Datensätzen (Codes) in ein einzelnes Feld im übergeordneten Datensatz (Projekte) des hinzugefügten, aktualisierten oder gelöschten untergeordneten Datensatzes ein.SQL-Abfrage zum Aktualisieren des übergeordneten Datensatzes mit untergeordneten Datensatzwerten

Ich bin beim Schreiben einer korrekten Abfrage fest, um die Code-Werte nur von diesen untergeordneten Datensätzen abzurufen, die die untergeordneten Elemente eines übergeordneten Datensatzes sind.

-- Create the test tables 
CREATE TABLE projects (
    ProjectId varchar(16) PRIMARY KEY, 
    ProjectName varchar(100), 
    Codestring nvarchar(100) 
) 
GO 
CREATE TABLE prcodes (
    CodeId varchar(16) PRIMARY KEY, 
    Code varchar (4), 
    ProjectId varchar(16) 
) 
GO 
-- Add sample data to tables: Two projects records, one with 3 child records, the other with 2. 
INSERT INTO projects 
(ProjectId, ProjectName) 
SELECT '101','Smith' UNION ALL 
SELECT '102','Jones' 
GO 
INSERT INTO prcodes 
(CodeId, Code, ProjectId) 
SELECT 'A1','Blue', '101' UNION ALL 
SELECT 'A2','Pink', '101' UNION ALL 
SELECT 'A3','Gray', '101' UNION ALL 
SELECT 'A4','Blue', '102' UNION ALL 
SELECT 'A5','Gray', '102' 
GO 

Ich bin auf, wie man eine korrekte Update-Abfrage erstellen. Können Sie helfen, diese Abfrage zu beheben?

-- Partially working, but stuffs all values, not just values from chile (prcodes) records of parent (projects) 
UPDATE proj 
SET 
proj.Codestring = (SELECT STUFF((SELECT ',' + prc.Code 
FROM projects proj INNER JOIN prcodes prc ON proj.ProjectId = prc.ProjectId 
ORDER BY 1 ASC FOR XML PATH('')),1, 1, '')) 

Das Ergebnis, das ich für die Codefolge Feld in Projekte erhalten ist:

ProjectId ProjectName Codestring 
    101  Smith  Blue,Blue,Gray,Gray,Pink 
    ... 

Aber das Ergebnis, das ich in Projekte für die Codefolge Feld benötigen, ist:

ProjectId ProjectName Codestring 
    101  Smith  Blue,Pink,Gray 
    ... 

Hier ist mein Anfang auf dem Auslöser. Die obige Update-Abfrage wird diesem Trigger hinzugefügt. Können Sie mir helfen, die Trigger-Erstellungsabfrage zu vervollständigen?

CREATE TRIGGER Update_Codestring ON prcodes 
AFTER INSERT, UPDATE, DELETE 
AS 
WITH CTE AS (
    select ProjectId from inserted 
    union 
    select ProjectId from deleted 
) 

Antwort

2

Der folgende Trigger wird ausgeführt, wie Sie möchten.

CREATE TRIGGER Update_Codestring ON prcodes 
AFTER INSERT, UPDATE, DELETE 
AS 
UPDATE projects 
SET Codestring = (SELECT STUFF((SELECT ',' + prc.Code 
    FROM projects proj INNER JOIN prcodes prc ON proj.ProjectId = prc.ProjectId 
    WHERE proj.ProjectId = projects.ProjectId 
    ORDER BY 1 ASC FOR XML PATH('')),1, 1, '')) 
where ProjectId in (SELECT ProjectId FROM inserted 
        UNION 
        SELECT ProjectId FROM deleted) 

Was Sie wurden in Ihrer ursprünglichen Update-Anweisung fehlen:

WHERE proj.ProjectId = projects.ProjectId - Dies wird die Unterabfrage nur das Projekt auswählen, die aktualisiert wird. projects ohne Alias ​​kommt von der update-Anweisung, so dass die Aktualisierung für jede Zeile in projects nur die aktuelle Projekt Zeile aktualisiert wird aktualisiert.

WHERE ProjectId IN (SELECT ProjectId FROM inserted UNION SELECT ProjectId FROM deleted) - Dadurch wird das Update so gefiltert, dass nur die Zeilen mit den geänderten untergeordneten Elementen betroffen sind.

Auch können Sie die Update-Anweisung vereinfachen, da es nicht die projects Tabelle zweimal benötigt inbegriffen:

CREATE TRIGGER Update_Codestring ON prcodes 
AFTER INSERT, UPDATE, DELETE 
AS 
UPDATE projects 
SET Codestring = (SELECT STUFF((SELECT ',' + prc.Code 
    FROM prcodes prc 
    WHERE prc.ProjectId = projects.ProjectId 
    ORDER BY 1 ASC FOR XML PATH('')),1, 1, '')) 
WHERE ProjectId IN (SELECT ProjectId FROM inserted 
        UNION 
        SELECT ProjectId FROM deleted) 

Schließlich tun Sie wirklich die Codestring auf Ihrem Projects Tabelle speichern müssen? Es ist etwas, das leicht in einer Abfrage jederzeit neu berechnet oder sogar in eine Ansicht gebracht werden kann. Das heißt, Sie müssen sich keine Gedanken darüber machen, dass Sie die zusätzlichen Daten speichern müssen und einen Auslöser haben müssen, um sie zu verwalten.

+0

shf301 - Vielen Dank für die Antwort. Ich werde Zeit haben, es morgen zu testen. Die Notwendigkeit für das Codestring-Feld ergibt sich aus der proprietären Datenbank, mit der wir arbeiten müssen, und aus den Einschränkungen unserer Fähigkeit, Felder anzupassen, die für die Benutzer verfügbar sind. –

+0

shf301 - Diese Antwort ist perfekt! Ich habe es heute Morgen getestet. Die Abfrage macht ** genau ** was wir brauchen. Vielen Dank! –

+0

@WellsAnderson - Großartig - dann bitte markieren Sie meine Antwort als die akzeptierte Antwort. – shf301

Verwandte Themen