2012-03-31 16 views
1

子レコード(コード)が追加、更新、または削除されたときに起動するトリガを作成する必要があります。トリガーは、追加、更新、または削除された子レコードの親レコード(プロジェクト)内の単一のフィールドに、すべての子レコード(コード)からコンマで区切られたコード値の文字列を埋め込みます。子レコードの値を持つ親レコードを更新するSQLクエリ

単一の親レコードの子である子レコードだけからCode値を取得するために、正しいクエリを書くことに固執しています。

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

は私のスタートですトリガで上記のUpdateクエリがこのTriggerに追加されます。トリガー作成クエリの実行を手伝ってもらえますか?

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

関連する問題