1

ビューでクエリを実行中にエラーが発生した場合に、テーブルへのビューの実行中の挿入に関するアラートをログに追加しようとしています。ビューを単独で実行すると、SUBSTRING に無効な入力が返されます (エラーの正確な文言は覚えていません)。ビュー -> テーブル ストアド プロシージャの一部として実行すると、エラーは無視されます。問題のある行を探して、ビューのコードで例外を作成し、結果からその行を除外する必要があります (わかっています。くだらないように聞こえますが、私は専用の webapp からの巨大な web-log ファイルのデータ削減を行っています) が、脱線します。

エラーをキャッチするために 2 つの異なる方法を試しましたが、どちらも実行結果テーブル (refresh_results) にエラーを示す行を挿入するような方法ではトリガーされません。私はいくつかの基本的なことを見逃しているかもしれないと思います - おそらくエラーはカプセル化されています。エラーを検出できない場合、エラーに気付く唯一の方法は、テーブルへのエントリ数が一定期間少ないことに誰かが気付いた場合です。

    SELECT @TransactionName = 'tname';
    BEGIN TRANSACTION @TransactionName;
    BEGIN TRY
      print 'tname ***In Try***';
      if exists (select name from sysobjects where name='tablename')
      begin
        drop table tablename;
      end
      select * into tablename 
      from opendatasource('SQLNCLI', 'Data Source=DATABASE;UID=####;password=####').dbo.viewname;
      COMMIT TRANSACTION @TransactionName;
    END TRY
    BEGIN CATCH 
      print 'tablename ***ERROR - check for SUBSTRING***';
      begin transaction
      set   @result_table = 'tablename ***ERROR - check for SUBSTRING***'
      select    @result_time = getdate(),
            @result_rows = count(logtime)
      from tablename
      insert INTO   [dbo].[refresh_results] (result_time, result_table, result_rows)
                values (@result_time, @result_table, @result_rows);
      commit transaction
      ROLLBACK TRANSACTION @TransactionName;
    END CATCH 

また

    if exists (select name from sysobjects where name='tablename')
    begin
      drop table tablename;
    end
    select * into tablename 
    from opendatasource('SQLNCLI', 'Data Source=DATABASE;UID=####;password=####').dbo.viewname;

    print '@@error' 
print @@error

if @@error <> 0 
Begin
      print 'tablename ***ERROR - check for SUBSTRING***';
      set     @result_table = 'tablename ***ERROR - check for SUBSTRING***'
      select  @result_time = getdate(),
          @result_rows = count(logtime)
      from tablename
      insert INTO   [dbo].[refresh_results] (result_time, result_table, result_rows)
                values (@result_time, @result_table, @result_rows);
    End
4

3 に答える 3

3

ネストされたトランザクションは、あなたが思っていることをしていません。保存したと思っていたエラーをロールバックしています。最初のトランザクションをロールバックしてから、必要に応じて新しいトランザクションを開始してエラーを記録します。

ここを参照してください。

于 2013-01-22T23:26:26.283 に答える
2

あなたは2つの別々の問題を抱えています

最初の例では、次のことを行うトランザクションを実行しています。

BEGIN TRAN
    ...error...
    BEGIN TRAN
        ...log error...
    COMMIT TRAN
ROLLBACK TRAN

内部トランザクションは外部トランザクションとともにロールバックされます。多分試してみてください:

BEGIN TRAN
    ...error...
ROLLBACK TRAN
BEGIN TRAN
    ...log error...
ROLLBACK TRAN

使用している2番目の例@@ERROR。私が理解しているように、実行するとすぐに何か@@ERRORが置き換えられます。私が思うに、それは印刷ステートメントを含みます。

次のようなものに変更した場合:

DECLARE @Error INT
select * into tablename 
from opendatasource('SQLNCLI', 'Data Source=DATA3;UID=;password=').dbo.viewname;

SET @Error = @@ERROR
print '@@error' 
print @Error

if @Error <> 0
...log the error

の利点はTRY CATCH、エラーが発生した場合にそれをキャッチすることです。この@@ERRORメソッドは100%機能しますが、最後の行の実行でのみ機能します。したがって、エラーが発生した場合DROP TABLE tablename @@ERRORは取得されません(別のチェックを追加しない限り)

于 2013-01-22T23:35:04.887 に答える
0

さて、ヘルパー プロシージャを使用してログ エントリを追加する必要がありました。何が起こっていたかは、ロールバックがログエントリもロールバックしていたということだと思います.

これは私がしなければならなかったことです:

    DECLARE @myError tinyint;
    BEGIN TRY
        BEGIN TRANSACTION;      
        if exists (select name from sys.sysobjects where name='table_name')
        begin
          drop table table_name
        end
        select * into table_name
          from opendatasource('SQLNCLI', 'Data Source=###;UID=###;password=###').view_Table
        COMMIT TRANSACTION;
    END TRY
    BEGIN CATCH 
        set @myError = 1                
        ROLLBACK TRANSACTION;
    END CATCH

    if @myError <> 0
    begin
        exec dbo.table error
    end
    ELSE
        EXEC  exec dbo.table normal row
于 2013-01-24T18:51:06.317 に答える