2016-09-28 17 views
1

アイテムテーブル&アイテムテーブルのすべての変更を記録するItems_Logテーブルがあります。TRIGGERのROLLBACKによりメッセージが表示される3609

CREATE TABLE [dbo].[Items] (
    [item_id] [int] IDENTITY(1,1) NOT NULL, 
    [item_name] [varchar](50) NOT NULL, 
    [item_desc] [varchar](250) NULL, 
    [modified_by_id] [int] NOT NULL, 
    [modified_date] [datetime] NOT NULL 
) 

CREATE TABLE [dbo].[Items_Log] (
    [item_log_id] [int] IDENTITY(1,1) NOT NULL, 
    [item_id] [int] NOT NULL, 
    [item_name] [varchar](50) NOT NULL, 
    [item_desc] [varchar](250) NULL, 
    [modified_by_id] [int] NOT NULL, 
    [modified_date] [datetime] NOT NULL 
) 

アイテムテーブルの更新は、SPROCで実行されます。それはどのような方法で更新されますときに、古いデータをログに記録するアイテムテーブル上のトリガがあり

CREATE PROCEDURE [dbo].[pUpdateItem] 
    @ItemID INT, 
    @Name VARCHAR(100), 
    @ByID INT 
AS 
    UPDATE [Items] SET 
    item_name = @Name, 
    --modified_by_id = @ByID, 
    modified_date = GETDATE() 
    WHERE item_id = @ItemID; 
GO 

(後述のように[modified_by_id]意図的に、コメントアウト)。 RAISERRORが呼び出されるように

ALTER TRIGGER [dbo].[tItemsUpdate] 
    ON [dbo].[Items] 
    AFTER UPDATE 
AS 
BEGIN 
    SET NOCOUNT ON; 

    IF (UPDATE(modified_by_id) AND UPDATE(modified_date)) 
    BEGIN 
     INSERT INTO [Items_Log] 
     SELECT * FROM Deleted 
    END 
    ELSE 
    BEGIN 
     RAISERROR ('[modified_by_id] and [modified_date] must be updated.', 16, 1) 
     ROLLBACK TRANSACTION 
    END 
END 

トリガーをテストするには、[modified_by_id]コメントアウトされています。

Msg 50000, Level 18, State 1, Procedure tItemsUpdate, Line 15 
[modified_by_id] and [modified_date] must be updated. 
Msg 3609, Level 16, State 1, Procedure pUpdateItem, Line 5 
The transaction ended in the trigger. The batch has been aborted. 

第1のエラーは明らかに私が見たいエラーであり、トランザクションは正しくロールバックされます。しかし、私は本当に、このようなユーザーのために表示されるので、2番目のエラーをスローせずに終了したい。

私は、他の場所で見てきた提案に基づいて、トランザクションとロールバックの正式な宣言と共に、SPROCでTry ... Catchを実行しようとしました(そして、ロールバックをトリガーから取り除く)。これはSPROCのように見えました。

BEGIN TRY 
    BEGIN TRANSACTION 
    UPDATE [Items] SET 
     item_name = @Name, 
     --modified_by_id = @ByID, 
     modified_date = GETDATE() 
    WHERE item_id = @ItemID; 
    COMMIT TRANSACTION 
END TRY 
BEGIN CATCH 
    ROLLBACK TRANSACTION 
END CATCH 

ここで更新は行われませんが、エラーメッセージは表示されません。 RAISERRORのものさえありません。

私は単純に "Msg 3609"を押せばいいと思う。そうすれば、すべてが私が望むやり方で動作させることができます。しかし、この時点で、私はほとんどすべての解決策を取ります。

誰もがこれを手伝ってくれますか?

答えて

0
BEGIN CATCH 
    SELECT 
     ERROR_NUMBER() AS ErrorNumber 
     ,ERROR_SEVERITY() AS ErrorSeverity 
     ,ERROR_STATE() AS ErrorState 
     ,ERROR_PROCEDURE() AS ErrorProcedure 
     ,ERROR_LINE() AS ErrorLine 
     ,ERROR_MESSAGE() AS ErrorMessage; 
    ROLLBACK TRANSACTION; 
END CATCH; 

https://msdn.microsoft.com/en-us/library/ms190358.aspx

または

BEGIN CATCH 
    DECLARE @ErrorSeverity INT, @ErrorState INT, @ErrorMessage VARCHAR(100); 
    SELECT @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(), @ErrorMessage = ERROR_MESSAGE(); 
    ROLLBACK TRANSACTION; 
    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState); 
END CATCH 
+0

[OK]を、私は、エラー情報をそのように取得していますが、今では戻って私のクラスにエラーを投げていません。キャプチャされた値でRAISERRORをやり直すことができたと思いますか? – Bob

+0

はい、おそらくいくつかの情報を追加すると、新しいエラーが発生する可能性があります。 – Serg

+0

うん、私はほぼすべてのSPROCをこの操作を行う必要がある場合、少しかさばることになるだろうが、これは私が今持っているものは基本的である: はCATCH DECLARE @ErrorSeverity INT' が '' @ErrorState INT' をDECLARE BEGIN @ErrorMessage VARCHAR(100) ' SET @ErrorSeverity = ERROR_SEVERITY() SET @ErrorState = ERROR_STATE() SET @ErrorMessage = ERROR_MESSAGE() ROLLBACKトランザクションを宣言します。 RAISERROR(@ ErrorMessage、@ErrorSeverity、@ErrorState); END CATCH ' – Bob

関連する問題