2012-03-31 2 views
1

자식 레코드 (코드)가 추가, 업데이트 또는 삭제 될 때 발생하는 트리거를 만들어야합니다. 트리거는 모든 하위 레코드 (코드)의 쉼표로 구분 된 코드 값 문자열을 추가, 업데이트 또는 삭제 된 하위 레코드의 상위 레코드 (프로젝트)의 단일 필드에 채 웁니다.부모 레코드를 자식 레코드 값으로 업데이트하는 쿼리

단일 상위 레코드의 하위 레코드 인 코드에서 코드 값을 검색하는 올바른 쿼리를 작성하는 중입니다.

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

내가 프로젝트에서 Codestring 필드 얻을 결과는 다음과 같습니다

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

하지만 프로젝트의 Codestring 필드에 필요한 결과는이 :

여기
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은 update 문에서 가져 오므로 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) 

을 마지막으로 당신이 정말로 당신의 Projects 테이블에 Codestring를 저장해야합니까? 언제든지 쿼리에서 쉽게 다시 계산하거나 심지어 뷰에 넣을 수도 있습니다. 그건 당신이 여분의 데이터를 저장하는 데 대해 걱정할 필요가 없었 그것을 유지하기위한 방아쇠를했습니다.

+0

shf301 - 답변 해 주셔서 감사합니다. 나는 내일 그것을 시험 할 시간이있을 것이다. Codestring 필드의 필요성은 우리가 작업해야만하는 독점적 인 데이터베이스와 사용자가 사용할 수있는 필드를 사용자 정의 할 수있는 능력에 대한 제약에서 비롯됩니다. –

+0

shf301 -이 답변은 완벽합니다! 나는 오늘 아침에 그것을 시험했다. 쿼리는 ** 정확히 ** 필요한 것을 수행합니다. 고맙습니다! –

+0

@WellsAnderson - 위대한 - 다음 내 대답을 허용 대답으로 표시하십시오. – shf301

관련 문제