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 服务器时,我仍然没有看到出现错误,因此客户端应用程序当然对错误一无所知。有谁知道为什么 DataSnap 服务器中没有出现“raiserror”和外键违规错误?

仅供参考 - 我使用的是 Delphi XE2 Enterprise 和 SQL Server 2008 R2,它们都在 Windows Server 2008 R2 上运行。

4

1 回答 1

0

解决方案最终变得非常简单。set nocount on;在 SQL 语句的开头添加修复了隐藏 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 回答