我需要创建一个触发器,在添加,更新或删除子记录(代码)时触发。触发器将一串逗号分隔的代码值从所有子记录(代码)填充到添加,更新或删除的子记录的父记录(项目)中的单个字段中。
我坚持写一个正确的查询来从那些作为单个父记录的子记录的子记录中检索代码值。
-- 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, ''))
我在Projects中获得的Codestring字段的结果是:
ProjectId ProjectName Codestring
101 Smith Blue,Blue,Gray,Gray,Pink
...
但我在Projects中的Codestring字段所需的结果是:
ProjectId ProjectName Codestring
101 Smith Blue,Pink,Gray
...
这是我在触发器上的开始。上面的更新查询将添加到此触发器。你能帮我完成Trigger创建查询吗?
CREATE TRIGGER Update_Codestring ON prcodes
AFTER INSERT, UPDATE, DELETE
AS
WITH CTE AS (
select ProjectId from inserted
union
select ProjectId from deleted
)
答案 0 :(得分: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
表上吗?它可以在任何时候在查询中轻松重新计算,甚至可以放入视图中。那就是你不必担心必须存储额外的数据并触发维护它。