2016-03-29 9 views
0

CHECKINOUTテーブルにデータを挿入した後、別のテーブルにデータを挿入するためにこのトリガを書きました。SQL Server:Insert Triggerの後に別のテーブルを更新する

ただし、Att_processテーブルにはデータが挿入されません。 SQL Serverにエラーは表示されません。この問題を理解する手助けはできますか?

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

CREATE TRIGGER [dbo].[trgAfterInsert] ON [dbo].[CHECKINOUT] 
AFTER INSERT 
AS 
    DECLARE @uid INT; 
    DECLARE @checkin DATETIME; 

    SELECT @uid = i.USERID 
    FROM [CHECKINOUT] i; 

    SELECT @checkin = i.CHECKTIME 
    FROM [CHECKINOUT] i; 

    IF(DATEPART(HOUR, @checkin) < 12) 
    BEGIN 
     INSERT INTO Att_process (USERID, checkin_time) 
     VALUES (@uid, @checkin); 
    END; 
    ELSE 
    BEGIN 
     INSERT INTO Att_process (USERID, checkout_time) 
     VALUES (@uid, @checkin); 
    END; 
+0

'SELECT @uid = i.USERID FROM inserted i; SELECT @checkin = i.CHECKTIME FROM inserted i; ' – artm

+2

@artm:それは**道のりではありません!**'挿入されました '*** ***には複数の行が含まれます - どちらがあなたですかここで選択しますか? 'Inserted'の**複数の行を適切に扱うためのトリガを書く必要があります! –

+0

@marc_s - ハハはよく言った!それは悪い修正でした –

答えて

2

二つの主要な問題:あなたは

  • あなたはトリガーを想定している、新たに挿入された行が含まれているInserted擬似テーブルを見ていない行ごとに一度呼ばれ

    • - これはではなくの場合、Inserted疑似表ごとに1回トリガーが呼び出されますので、代わりにこのコードを試してみて、あなたはその

    に対処する必要がある - 複数の行が含まれています。あなたが最後に挿入されたデータを抽出するために「挿入」魔法のテーブルを使用していないので、

    CREATE TRIGGER [dbo].[trgAfterInsert] ON [dbo].[CHECKINOUT] 
    AFTER INSERT 
    AS 
        -- grab all the rows from the "Inserted" pseudo table 
        -- and insert into the "checkin_time" column, if the value 
        -- of the HOUR is less than 12 
        INSERT INTO Att_process (USERID, checkin_time) 
         SELECT 
          i.USERID, i.CHECKTIME 
         FROM 
          Inserted i 
         WHERE 
          DATEPART(HOUR, i.CHECKTIME) < 12 
    
        -- grab all other rows (HOUR is greater than or equal to 12) 
        -- and insert into the "checkout_time" column 
        INSERT INTO Att_process (USERID, checkout_time) 
         SELECT 
          i.USERID, i.CHECKTIME 
         FROM 
          Inserted i 
         WHERE 
          DATEPART(HOUR, i.CHECKTIME) >= 12 
    
  • -1

    は、これを試してみてください。

    DECLARE @uid INT; 
    DECLARE @checkin DATETIME; 
    
    SELECT @uid = USERID FROM inserted 
    
    SELECT @checkin = CHECKTIME FROM inserted 
    
    +0

    **それは行く方法ではありません!** INSERTが複数の項目を挿入した場合、 'Inserted'は複数の行を含みます。 'Inserted'の複数の行**を適切に処理するためのトリガーを書く必要があります! –

    +0

    mysqlで同じテーブルを持っているので、同じことをMysqlで行う方法を教えてもらえますか? –

    1

    多くのSQL開発者が行ったように、SQL Serverトリガでも同じエラーが発生しました。テーブルに複数の挿入ステートメントが実行されている場合は、不足しています。 トリガーは、各行ではなくSQL文に対して1回だけ実行されます。 したがって、トリガー内のコードは、SQL文の影響を受けるすべての行のすべてのタスクをカバーできる必要があります。

    ここでは、トリガーコードを変更する方法の例を示します。

    ALTER TRIGGER [dbo].[trgAfterInsert] ON [dbo].[CHECKINOUT] 
    AFTER INSERT 
    AS 
    
    INSERT INTO Att_process (USERID, checkin_time, checkout_time) 
    select 
        USERID, 
        case when DATEPART(HOUR, CHECKTIME) < 12 then CHECKTIME else null end, 
        case when DATEPART(HOUR, CHECKTIME) < 12 then null else CHECKTIME end 
    FROM inserted 
    

    安定した結果を得るためには、トリガーコード内で使用可能な挿入済みテーブルと削除済み内部テーブルを使用してください。

    サンプルSQL Trigger to log changesで、削除済みテーブルと挿入済みテーブルの使用方法をさらに確認できます。

    私はそれがあなたの役に立てば幸い

    一つの最後のノート、あなたが同時にSQL Output clause to insert data into two tablesを使用することができます。 もちろん、トリガはテーブルベースで動作します。したがって、insertステートメントが実行された場所で作業がトリガされます。 Output句を使用する場合、そのテーブルにデータを挿入する唯一のSQL文は、2つのテーブル間の一貫性を維持することになります。

    +0

    こんにちはEralper、mysqlでも同じテーブルを持っているので、Mysqlで同じことをする方法を教えてくれますか? –

    関連する問題