web-dev-qa-db-ja.com

変更された列の値を見つける

表1

 ID |COL2|COL3|COL4|COL5|
ROW1|  1 |  1 | 1  | 1  |
ROW2|  1 |  3 | 2  | 6  |
ROW3|  1 |  1 | 1  | 1  |
ROW4|  1 |  1 | 1  | 1  |
ROW5|  1 |  1 | 1  | 1  |
ROW6|  1 |  1 | 1  | 1  |

問題

テーブル1を更新した後、値が変更された新しい行があります。

 ID | COL2 | COL3 | COL4 | COL5 | 
 ROW1 | 1 | 1 | 1 | 1 | 
 ROW2 | 1 | 45  | 
 ROW3 | 1 | 1 | 1 | 1 | 
 ROW4 | 1 | 1 | 1 | 1 | 
 ROW5 | 1 | 1 | 1 | 1 | 
 ROW6 | 1 | 1 | 1 | 1 | 

列名に基づいて複数の行に変更されたテーブル1の行を選択します。

望ましい出力

ID  |OLD|NEW|
ROW2| 3 | 0 |
ROW2| 2 | 4 |
ROW2| 6 | 5 |

私の試み

私は次のようなトリガーを作成しました:

select d.col2 as old, i.col2 as new 
from inserted i 
inner join deleted d 
    on i.id = d. id 
where not exists
(
    select i.row2 
    intersect 
    select d.row2
) 

...しかし、1行だけを返します。

希望する出力をどのように達成できますか? SQL Server 2008を使用しています。

4
magniche

サンプルテーブルとデータ

CREATE TABLE dbo.Table1
(
    RowID integer IDENTITY PRIMARY KEY,
    Col2 integer NULL,
    Col3 integer NULL,
    Col4 integer NULL,
    Col5 integer NULL
);

INSERT dbo.Table1
    (Col2, Col3, Col4, Col5)
VALUES
    (1, 1, 1, 1),
    (1, 3, 2, 6),
    (1, 1, 1, 1),
    (1, 1, 1, 1),
    (1, 1, 1, 1),
    (1, 1, 1, 1);

Sample data

引き金

CREATE TRIGGER Table1_AU
ON dbo.Table1
AFTER UPDATE
AS
BEGIN
    SET ROWCOUNT 0;
    SET NOCOUNT ON;

    SELECT
        I.RowID,
        Changed.Name,
        Changed.Old,
        Changed.New
    FROM Inserted AS I
    JOIN Deleted AS D
        ON D.RowID = I.RowID
    CROSS APPLY
    (
        -- Unpivot only changed columns
        SELECT 'Col2', D.Col2, I.Col2
        WHERE NOT EXISTS (SELECT D.Col2 INTERSECT SELECT I.Col2)
        UNION ALL
        SELECT 'Col3', D.Col3, I.Col3
        WHERE NOT EXISTS (SELECT D.Col3 INTERSECT SELECT I.Col3)
        UNION ALL
        SELECT 'Col4', D.Col4, I.Col4
        WHERE NOT EXISTS (SELECT D.Col4 INTERSECT SELECT I.Col4)
        UNION ALL
        SELECT 'Col5', D.Col5, I.Col5
        WHERE NOT EXISTS (SELECT D.Col5 INTERSECT SELECT I.Col5)
    ) AS Changed (Name, Old, New)
    WHERE NOT EXISTS
    (
        -- Only changed rows
        SELECT I.Col2, I.Col3, I.Col4, I.Col5
        INTERSECT
        SELECT D.Col2, D.Col3, D.Col4, D.Col5
    );
END;

更新ステートメント

UPDATE dbo.Table1
SET Col3 = 0,
    Col4 = 4,
    Col5 = 5
WHERE
    RowID = 2;

出力

Output

トリガーから返される結果は非推奨ですが、おそらく問題は実際の要件の簡略版です。このコードは、RowID列が決して変更されないことを前提としています(この例では、identityプロパティのため変更できません)。

3
Paul White 9