2015-01-07 8 views
5

多くの変数を使用せずにこの更新トリガを書き直す方法を教えてください。最初のT-SQL更新トリガを最適化する必要があります

私は最初のSQL Serverトリガを書きましたが、うまくいきましたが、より簡単な解決策が必要だと思います。

5つの列のうち少なくとも1つが変更された場合、別の表に2つの新しい行が書き込まれます。 行1 =古いFahrer(=ドライバ)と古いdispodateと更新時間 行2 =新しいFahrerと新しいdispodateとupdatedatetime 私の解決策はfoxpro-triggerの単なるコピーですが、T 1つの列が変更されているかどうかを確認する-SQL。

ALTER TRIGGER [dbo].[MyTrigger] 
ON [dbo].[tbldisposaetze] 
AFTER UPDATE 
AS 
SET NOCOUNT ON; 
/*SET XACT_ABORT ON 
SET ARITHABORT ON 
*/ 
DECLARE @oldfahrer varchar(10) 
DECLARE @oldbus varchar(10) 
DECLARE @olddispodat date 
DECLARE @oldvzeit decimal(4,0) 
DECLARE @oldbzeit decimal(4,0) 
DECLARE @oldbeschreibk varchar(255) 

DECLARE @newfahrer varchar(10) 
DECLARE @newbus varchar(10) 
DECLARE @newdispodat date 
DECLARE @newvzeit decimal(4,0) 
DECLARE @newbzeit decimal(4,0) 
DECLARE @newbeschreibk varchar(255) 

    SELECT @oldfahrer = fahrer,@oldbeschreibk=beschreibk,@oldbus=bus,@oldbzeit=bzeit,@olddispodat=dispodat,@oldvzeit=vzeit 
     FROM DELETED D 
    SELECT @newfahrer = fahrer,@newbeschreibk=beschreibk,@newbus=bus,@newbzeit=bzeit,@newdispodat=dispodat,@newvzeit=vzeit 
     FROM inserted I 

if @oldbeschreibk <> @newbeschreibk or @oldbus <> @newbus or @oldbzeit <> @newbzeit or @oldfahrer <> @newfahrer or @oldvzeit <> @newvzeit 
begin 
    IF (SELECT COUNT(*) FROM tbldispofahrer where [email protected] and [email protected]) > 0 
    update tbldispofahrer set laenderung = GETDATE() where [email protected] and [email protected] 
    else 
    INSERT into tbldispofahrer (fahrer,dispodat,laenderung) VALUES (@oldfahrer,@olddispodat,getdate()) 

    IF (SELECT COUNT(*) FROM tbldispofahrer where [email protected] and [email protected]) > 0 
    update tbldispofahrer set laenderung = GETDATE() where [email protected] and [email protected] 
    else 
    INSERT into tbldispofahrer (fahrer,dispodat,laenderung) VALUES (@newfahrer,@newdispodat,getdate()) 
end 
+1

!!これまでどんなトリガーでも。削除され挿入されたテーブルには複数のレコードが含まれている可能性があります。 – HLGEM

+0

あなたのトリガーは、あなたが**行ごとに一度**呼び出されると仮定しているように見えるという点で、**主な**の欠陥を持っています** - **そうではありません。トリガは**文ごとに** **起動します。したがって、 'UPDATE'文が25行に影響を与えると、トリガは一度**発生しますが、' Inserted'と 'Deleted'はそれぞれ25行。あなたの 'SELECT'コードは25行のどれを選択しますか?それは非決定的です。これを考慮に入れてトリガーを書き直す必要があります。 –

+0

'tbldispofahrer'テーブルの主キー列は何ですか? –

答えて

4

SQL Server 2008以上があると仮定します。変数を指定せずに1つのステートメントですべてを行うことができます。

変数を最初に取得し、一致しないかどうかを調べる代わりに、where節の部分で簡単に行うことができます。コメントの中に人が言ったように、挿入され削除された行の一部として複数の行を持つことができます。同じ更新行で作業していることを確認するには、主キーで一致する必要があります。

行を挿入または更新するには、MERGEステートメントを使用しています。マージのソースは上記のwhere節を持つユニオンです。ユニオン内のトップテーブルは古いファーラーを持ち、ボトムは新しいファーラーを持っています。あなたの内側のIFと同じように、既存の行はfarherとdispodatでマッチし、適切に挿入または更新されます。

あなたの例では、newfahrerとoldfahrerはまったく同じであるため、挿入または更新が1つしか発生しないようにすることができます(つまり、bzeitが異なる場合)。組合は重複データが挿入されるのを防ぐべきです。私はマージがあるとエラーになると信じています。

MERGE tbldispofahrer AS tgt 
USING (
    SELECT d.farher, d.dispodat, GETDATE() [laenderung] 
    INNER JOIN inserted i ON i.PrimaryKey = d.PrimaryKey 
     AND (i.fahrer <> d.fahrer OR i.beschreibk <> d.beschreik ...) 
    UNION 
    SELECT i.farher, i.dispodat, GETDATE() [laenderung] 
    INNER JOIN inserted i ON i.PrimaryKey = d.PrimaryKey 
     AND (i.fahrer <> d.fahrer OR i.beschreibk <> d.beschreik ...) 
) AS src (farher, dispodat, laenderung) 
ON tgt.farher = src.farher AND tgt.dispodat = src.dispodat 
WHEN MATCHED THEN UPDATE SET 
    laenderung = GETDATE() 
WHEN NOT MATCHED THEN 
    INSERT (fahrer,dispodat,laenderung) 
    VALUES (src.fahrer, src.dispodat, src.laenderung) 
1

Danielの回答には、構文エラーが多少あります。 次のコードは、罰金実行されている:[OK]を、最初あなたがすべてで、このような変数を使用するべきではありません

MERGE tbldispofahrer AS tgt 
 
USING (
 
    SELECT d.fahrer, d.dispodat, GETDATE() [laenderung] from deleted d 
 
    INNER JOIN inserted i ON i.satznr = d.satznr 
 
     AND (i.fahrer <> d.fahrer OR i.beschreibk <> d.beschreibk or i.bus <> d.bus or i.bzeit <> d.bzeit or i.vzeit <> d.vzeit) 
 
    UNION 
 
    SELECT i.fahrer, i.dispodat, GETDATE() [laenderung] from inserted i 
 
    INNER JOIN deleted d ON i.satznr = d.satznr 
 
     AND (i.fahrer <> d.fahrer OR i.beschreibk <> d.beschreibk or i.bus <> d.bus or i.bzeit <> d.bzeit or i.vzeit <> d.vzeit) 
 
) AS src (fahrer, dispodat, laenderung) 
 
ON tgt.fahrer = src.fahrer AND tgt.dispodat = src.dispodat 
 
WHEN MATCHED THEN UPDATE SET 
 
    laenderung = GETDATE() 
 
WHEN NOT MATCHED THEN 
 
    INSERT (fahrer,dispodat,laenderung) 
 
    VALUES (src.fahrer, src.dispodat, src.laenderung);

関連する問題