2012-03-31 88 views
1

我需要創建一個觸發器,用於在添加,更新或刪除子記錄(代碼)時觸發。觸發器將所有子記錄(代碼)中逗號分隔的代碼值的字符串填充到添加,更新或刪除的子記錄的父記錄(項目)中的單個字段中。SQL Query用子記錄值更新父記錄

我一直在寫一個正確的查詢來檢索來自那些子單記錄的子記錄的代碼值。

-- 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 

我被困在如何創建正確的更新查詢。 你能幫助解決這個問題嗎?

-- 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, '')) 

結果我得到了在項目的碼流場:

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

但我需要在項目的碼流場的結果是:

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

這裏是我的開始在觸發器上。上面的更新查詢將被添加到此觸發器。你能幫我完成觸發器創建查詢嗎?

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

回答

2

以下觸發器將按照您的需要執行。

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) 

您在原始更新語句中缺少什麼:

WHERE proj.ProjectId = projects.ProjectId - 這會子查詢過濾,僅正在更新項目。 projects沒有來自更新語句的別名,因此更新應用於projects中的每一行,只更新當前項目行。

WHERE ProjectId IN (SELECT ProjectId FROM inserted UNION SELECT ProjectId FROM deleted) - 這將過濾更新以僅影響具有更改的子級的行。

還可以簡化更新語句,因爲它並不需要包括兩次projects表:

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) 

最後你真的需要在Codestring存儲在您的Projects表?它可以隨時在查詢中輕鬆重新計算,甚至可以放入視圖中。那就是你不必擔心必須存儲額外的數據並且有觸發器來維護它。

+0

shf301 - 謝謝你的回答。明天我將有時間測試它。對Codestring字段的需求來自於我們必須使用的專有數據庫以及對我們定製可用於用戶的字段的能力的限制。 – 2012-04-01 01:55:19

+0

shf301 - 這個答案很完美!我今天早上測試了它。查詢完全**我們需要的。謝謝! – 2012-04-01 14:32:50

+0

@WellsAnderson - 太好了 - 那麼請將我的答案標記爲已接受的答案。 – shf301 2012-04-01 17:51:20