トリガーで「する」ことができるたくさんのものがありますが、そうする必要はありません。私は、すべてのコストでトリガー内のスカラー変数を設定することを避けることを強く勧めます。たとえあなたのテーブルがアプリケーションごとに1行挿入されることは決してありませんが、それはアプリケーションがどのように設計されているかによって決まります...すべてのトランザクションがアプリケーションを経由するわけではないことがわかった場合、あなたは非常に失礼です。
以下のトリガーの両方のタイプの簡単なデモがある...
USE tempdb;
GO
IF OBJECT_ID('tempdb.dbo.PrimaryTable', 'U') IS NOT NULL
DROP TABLE dbo.PrimaryTable;
GO
IF OBJECT_ID('tempdb.dbo.TriggerScalarLog', 'U') IS NOT NULL
DROP TABLE dbo.TriggerScalarLog;
GO
IF OBJECT_ID('tempdb.dbo.TriggerMultiRowLog', 'U') IS NOT NULL
DROP TABLE dbo.TriggerMultiRowLog;
GO
CREATE TABLE dbo.PrimaryTable (
Pt_ID INT NOT NULL IDENTITY (1,1) PRIMARY KEY CLUSTERED,
Col_1 INT NULL,
Col_2 DATE NOT NULL
CONSTRAINT df_Col2 DEFAULT (GETDATE())
);
GO
CREATE TABLE dbo.TriggerScalarLog (
Pt_ID INT,
Col1_Old INT,
Col1_New INT,
Col2_Old DATE,
Col2_New DATE
);
GO
CREATE TABLE dbo.TriggerMultiRowLog (
Pt_ID INT,
Col1_Old INT,
Col1_New INT,
Col2_Old DATE,
Col2_New DATE
);
GO
--=======================================================
CREATE TRIGGER dbo.PrimaryCrudScalar ON dbo.PrimaryTable
AFTER INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON;
DECLARE
@Pt_ID INT,
@Col1_Old INT,
@Col1_New INT,
@Col2_Old DATE,
@Col2_New DATE;
SELECT
@Pt_ID = ISNULL(i.Pt_ID, d.Pt_ID),
@Col1_Old = d.Col_1,
@Col1_New = i.Col_1,
@Col2_Old = d.Col_2,
@Col2_New = i.Col_2
FROM
Inserted i
FULL JOIN Deleted d
ON i.Pt_ID = d.Pt_ID;
INSERT dbo.TriggerScalarLog (Pt_ID, Col1_Old, Col1_New, Col2_Old, Col2_New)
VALUES (@Pt_ID, @Col1_Old, @Col1_New, @Col2_Old, @Col2_New);
GO -- DROP TRIGGER dbo.PrimaryCrudScalar;
CREATE TRIGGER PrimaryCrudMultiRow ON dbo.PrimaryTable
AFTER INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON;
INSERT dbo.TriggerMultiRowLog (Pt_ID, Col1_Old, Col1_New, Col2_Old, Col2_New)
SELECT
ISNULL(i.Pt_ID, d.Pt_ID),
d.Col_1,
i.Col_1,
d.Col_2,
i.Col_2
FROM
Inserted i
FULL JOIN Deleted d
ON i.Pt_ID = d.Pt_ID;
GO -- DROP TRIGGER dbo.TriggerMultiRowLog;
--=======================================================
--=======================================================
-- --insert test...
INSERT dbo.PrimaryTable (Col_1)
SELECT TOP 100
o.object_id
FROM
sys.objects o;
SELECT 'INSERT Scarar results';
SELECT * FROM dbo.TriggerScalarLog tsl;
SELECT 'INSERT Multi-Row results';
SELECT * FROM dbo.TriggerMultiRowLog tmrl;
UPDATE pt SET
pt.Col_1 = pt.Col_1 + rv.RandomVal,
pt.Col_2 = DATEADD(DAY, rv.RandomVal, pt.Col_2)
FROM
dbo.PrimaryTable pt
CROSS APPLY (VALUES (ABS(CHECKSUM(NEWID())) % 10000 + 1)) rv (RandomVal);
SELECT 'UPDATE Scarar results';
SELECT * FROM dbo.TriggerScalarLog tsl;
SELECT 'UPDATE Multi-Row results';
SELECT * FROM dbo.TriggerMultiRowLog tmrl;
DELETE pt
FROM
dbo.PrimaryTable pt;
SELECT 'DELETE Scarar results';
SELECT * FROM dbo.TriggerScalarLog tsl;
SELECT 'DELETE Multi-Row results';
SELECT * FROM dbo.TriggerMultiRowLog tmrl;
スカラーオプションを使用すると、単にレコードを移動するだけで、ソーステーブルに残る必要はありません。また、ISNULL(i.Pt_ID、d.Pt_ID)について説明してください。 – user3255066
私はスカラーオプションをこれまでどおりに使用しません。ソーステーブルからDELETEしたい場合は、トリガーではなくストアドプロシージャで処理します。 1つのテーブルでの特別な保守によって意図しない別のデータの削除が発生する可能性はありません。実際には、トリガの使用を主張するユースケースはごくわずかです...監査履歴の管理や、2つの異なる環境で2つのテーブルが互いに同期していることを確認することなどがあります。それはそれです。 –
ISNULL(i.Pt_ID、d.Pt_ID)... UPDATE文は2つのテーブルを生成します(Inserted&Deleted)...私の例では、IDごとに1つの監査行を生成したかったので、挿入されたIDと削除されたID(FULL JOIN Deleted d ON i.Pt_ID = d.Pt_ID)とISNULL(i.Pt_ID、d.Pt_ID)の完全結合は、単に "INSERTの場合はi.Pt_IDこれがDELETEであれば、d.Pt_IDを使用してください。これがUPDATEの場合は、同じ値なのでどちらを気にしなくてもかまいません。 –