2010-12-03 6 views
7

次のSQL文は、ネストされた詳細で例外をスローするSQLの良い例です。私は外側の例外の詳細Could not create constraint. See previous errors(非常に便利ではありません!)を得ることができるだけの文のキャッチ部分にあるようです。私は何を取得したいことは、内部例外メッセージである:「TABLE2」テーブルにFOREIGN KEY制約 「FK_TWO」を紹介SQL Serverのtry-catch内部例外メッセージconundrum

は サイクルまたは複数のカスケードパスを引き起こす可能性があります。 ON DELETE NO ACTIONまたはON UPDATE NO ACTIONを指定するか、他の FOREIGN KEY制約を変更してください( このメッセージはtry-catchなしでコード を実行することによって得られます)。

Catchブロックでは、どのようにT-SQLでこれを達成できますか?

BEGIN TRY 
     BEGIN TRAN; 

     CREATE TABLE TABLE1 (USER_ID INTEGER NOT NULL PRIMARY KEY, USER_NAME 
      CHAR(50) NOT NULL); 

     CREATE TABLE TABLE2 (AUTHOR_ID INTEGER NOT NULL PRIMARY KEY, AUTHOR_NAME 
      CHAR(50) NOT NULL, LASTMODIFIEDBY INTEGER NOT NULL, ADDEDBY INTEGER NOT 
      NULL); 

     ALTER TABLE TABLE2 ADD CONSTRAINT FK_ONE FOREIGN KEY (LASTMODIFIEDBY) 
      REFERENCES TABLE1 (USER_ID) ON DELETE CASCADE ON UPDATE CASCADE; 

     ALTER TABLE TABLE2 ADD CONSTRAINT FK_TWO FOREIGN KEY (ADDEDBY) 
      REFERENCES TABLE1(USER_ID) ON DELETE NO ACTION ON UPDATE CASCADE; 

     COMMIT TRAN; 
END TRY 
BEGIN CATCH 

     DECLARE @ERROR_MSG NVARCHAR(MAX), @SEVERITY INT, @STATE INT 
     SELECT @SEVERITY = ERROR_SEVERITY(), @STATE = ERROR_STATE() 
      , @ERROR_MSG = ERROR_MESSAGE() + ' err src line: ' + CAST(ERROR_LINE() AS NVARCHAR(20)) + ' ' + ISNULL(ERROR_PROCEDURE(), ''); 

     ROLLBACK; 
     -- RE-THROW EXCEPTION FOR DIAGNOSTIC VISIBILITY 
     RAISERROR (@ERROR_MSG ,@SEVERITY, @STATE); 
END CATCH; 

[編集]

は、だから、この問題の解決策がないことをした後ずっと探しているようです。うまくいけば、将来のバージョンでこれを修正する予定です。

+1

私はこれを行う方法がないと思います。この関連する質問も参照してください:[単一のステートメントから複数のエラーメッセージを取り込む](http://stackoverflow.com/questions/3697492/capturing-multiple-error-messages-from-a-single-statement) –

答えて

0

今、この問題を解決する方法はありません。 thisによれば、SQL Serverの次のバージョンのソリューションは、両方のエラーを再発生させる新しいthrowキーワードを使用することになります。

+0

[可能性があります出力バッファを解析して動作させることを迷惑を払っても構わないと思うなら、解決策!」(http://stackoverflow.com/questions/3697492/capturing-multiple-error-messages-from-a-single-statement/5773071) #5773071) –

9

元のエラーを再スローすることはできません。 エラーが発生し、エラー番号が50000以上で、キャプチャされたエラーメッセージが含まれています。例えばException handling and nested transactionsを参照してください。

begin catch 
    declare @error int, @message varchar(4000), @xstate int; 
    select @error = ERROR_NUMBER() 
     , @message = ERROR_MESSAGE(); 
raiserror ('Caught exception: %d: %s', 16, 1, @error, @message) ; 
return; 
end catch 

私はリンク先の記事にも必須XACT_STATE()チェックをカバーし、トランザクションのセマンティクスでのtry/catchブロックを混合、より徹底した例があります。

throw;を引数なしで発行でき、他のtry/catch言語のように元の例外を発生させるため、次のバージョン( "Denali")ではこの問題は修正されています。 TRY CATCH THROW: Error handling changes in T-SQL

はD'は、ああ、私は一種の対角線で記事を読ん

を更新しました参照してください。より多くの例外が発生した場合は、1つしかキャッチできません。デナリもそうだ。しかし、ほとんどの場合例外は重大度0(例外ではなく実際に印刷されていることを意味します)であり、依然として情報メッセージ(SqlConnection.InfoMessageイベント)としてクライアントに送信されます。