1

削除される前に削除されたレコードをログに記録するDataSnapメソッドがあります。削除が失敗した場合は、ログレコードも保持されないようにトランザクションをロールバックします。失敗の典型的な理由は、削除されているレコードが別のテーブルで使用されていることです。

私のSQLは次のようになります。

begin transaction
begin try
  insert into audit ([fields]) values ([the vlaues])
  delete [sometable] where [id] = [someid]
  commit transaction
end
begin catch
  rollback transaction
end catch

これは問題なく機能します。ただし、エラーメッセージは抑制されるため、DataSnapサーバーはエラーメッセージを認識しません。SQL構文エラーは常にエラーメッセージを表示し、その他の挿入/更新の一意キーおよび外部キー違反は常にエラーを返します。このコードがエラーを抑制する理由がわかりません。DataSnapコードは単純です。

procedure TMyClass.DeleteRecord([params]);
var
  qry: TSQLQuery;
begin
  qry := TSQLQuery.Create;
  ...
  qry.CommandText := [sql from above];
  qry.ParamByName('[params]').Value := [Values];
  qry.ExecSQL; // <- No error is raised here
end;

クエリは問題なく実行されるため、構文エラーやパラメータのバインドに関する問題は発生しません。外部キー違反エラーは表示されません。SQL Management StudioでSQLを実行すると、常にエラーが表示されます...そこでcatch、次のようにブロックを変更してみました。

try catch
  rollback transaction
  raiserror(N'Test Error Message', 16, 1)
end catch

DataSnapサーバーのデバッグ時にエラーが発生することはまだありません。そのため、もちろんクライアントアプリはエラーについて何も知りません。'raiserror'と外部キー違反エラーがDataSnapサーバーに表示されない理由を誰かが知っていますか?

参考までに-私はDelphiXE2EnterpriseとSQLServer2008R2をすべてWindowsServer2008R2で実行しています。

4

1 に答える 1

0

解決策は非常に単純なものになりました。SQLステートメントの先頭に追加するset nocount on;と、DataSnapからエラーが隠される問題が修正されました。私は以前にこれを見たことがありますが、主にデータが返されるときです。これはを使用しているので、ここでも必要なqry.ExecSQL();ことは私には起こりませんでした。nocount

トランザクションをロールバックした後にSQLエラーを再発生させるために使用するコードは次のとおりです。

set nocount on;
begin transaction
begin try
  insert into audit ([fields]) values ([the vlaues])
  delete [sometable] where [id] = [someid]
  commit transaction
end
begin catch
  declare @eMsg nvarchar(2048), @eSv int, @eSt int
  select @eMsg = error_message(), @eSv = error_severity(), @eSt = error_state()
  rollback transaction
  raiserror(@eMsg, @eSv, @eSt)
end catch

これで、必要に応じて、再発生したエラーがクライアントアプリケーションに表示されます。

于 2012-04-27T17:26:56.360 に答える