【问题标题】:ADO Command running multiple SQL statements: can't get error message back: USE THE Connection.Errors collection运行多个 SQL 语句的 ADO 命令:无法返回错误消息:使用 Connection.Errors 集合
【发布时间】:2012-05-18 04:39:19
【问题描述】:

我在各种表上都有一些触发器,它们使用 raiserror 告诉用户他试图做坏事。我想以原子方式运行多个插入和更新,如果其中一个触发器这么说,则回滚。我前世很邪恶,所以我使用 Access VBA。

如果第一条语句有问题,我的 VBA 中会出现运行时错误。但是,如果第二个或后续语句调用 raiserror 则我看不到任何错误消息。

解决方案:检查 connection.Errors 集合。

这是一个 Access 2007 ADP 前端和一个 SQL 2005 数据库。

下面的 VBA 是显示效果的最低限度。如果我将所有原子语句包装在存储过程中,我会得到相同的效果。

我认为我很聪明,将我的验证尽可能靠近数据库。显然不是!

如果您愿意尝试下面的代码,请在 CommandText 中交换 s1 和 s2 的顺序并欣赏不同的结果。

Public Sub TestSqlErrors2()
'CREATE TABLE [dbo].[tblStuff]([id] [int] IDENTITY primary key NOT NULL,[stuff] [varchar](255) NULL)
Dim cmd As ADODB.Command
Dim cnn As ADODB.Connection
Dim r As Long
Dim s1 As String
Dim s2 As String

s1 = " insert into tblStuff(stuff) values ('aaa')  "
s2 = " if 1=1 begin raiserror ('me, i''m just a lawnmower',16,1)  rollback transaction end "

Set cnn = Application.CurrentProject.Connection
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = cnn
'cnn.BeginTrans 'makes no difference
cmd.CommandText = "begin transaction " & s2 & s1 & " commit transaction "
cmd.Execute r
'cnn.CommitTrans
'cnn.Errors.count is either 2 or 0
End Sub

我尝试了各种组合。在下面的存储过程中,我明确(重新)提出了一个错误。但是,该错误不会传递回 VBA。

--CREATE TABLE [dbo].[tblStuff]([id] [int] IDENTITY primary key NOT NULL,[stuff] [varchar](255) NULL)
alter proc AddMoreStuff2
as
begin try
  begin transaction
  --swap the two statements below around to see the difference
  --if the first statement is raiserror then a run-time error appears in VBA
  --if not, no error appears in VBA, although no records are added
  insert into tblStuff(stuff) values ('aaa') 
  if 1=1 begin raiserror ('me, i''m just a lawnmower',16,1)  rollback transaction     end
  commit transaction
end try
begin catch
  declare @errormessage varchar(1024)
  set @errormessage = error_message()
  raiserror ( @errormessage, 16, 1 )
end catch

调用这个新过程的 VBA 代码是...

Public Sub TestSqlErrors2()
Dim cmd As ADODB.Command
Dim cnn As ADODB.Connection
Dim r As Long

Set cnn = Application.CurrentProject.Connection
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = cnn

cmd.CommandText = "exec AddMoreStuff2"
cmd.Execute r

End Sub

【问题讨论】:

  • 您使用的是哪种数据库/数据容器?我假设它必须是 SQL Server?

标签: sql vba ms-access ado adodb


【解决方案1】:

请看http://support.microsoft.com/kb/254304

PRB:ADO 错误集合不包含用户定义的错误 消息

使用 ActiveX 数据执行 SQL Server 存储过程 (SP) 对象 (ADO) 不填充 带有在 SP 中引发的用户定义错误的连接对象。 此行为仅在使用 SQL 的 OLE DB 提供程序时发生 服务器 (SQLOLEDB) 建立到 SQL Server 数据库的 ADO 连接。

您必须在 sql 脚本的开头显式设置 nocount。

【讨论】:

  • 感谢您的回答;请注意,这个问题已经很老了,您可能永远不会得到反馈。
  • 谢谢!幸运的是我已经完成了那个项目,但至少我知道我没有发疯......
  • 为了记录,这只有效,因为该语句是插入/更新。如果您使用 select 放置,那么它仍然无法工作(除非 select 不应该产生任何输出)。例如。 "select 'dummy'; exec procRaisError;"(procRaisError 使用内置 raiserror 引发错误)。
【解决方案2】:

DAO 不会引发 VBA 错误,但会填充连接 .Errors 集合。所以我可以在每次 Execute 调用后检查这个以获取错误描述。例如:

Dim errorMessage As String
Dim e As Object
For Each e In cnn.Errors
    errorMessage = errorMessage & e.Description
Next
If Len(errorMessage) > 0 Then
    Err.Raise 64000 - 1, Left(cmd.CommandText, 20), errorMessage
End If

【讨论】:

    猜你喜欢
    • 2014-04-27
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    • 1970-01-01
    • 2017-08-30
    • 1970-01-01
    • 2012-07-07
    相关资源
    最近更新 更多