2012-03-31 82 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