我有一个SQL Server存储过程。如果我在代码周围放置try块,它只会捕获某些错误,而只是将一些错误推送到SSMS消息窗口。我认为文档(TryCatch)表示try..catch块未捕获某些错误(例如,从不存在的表中进行选择)
在我的例子中,示例是通过同义词选择不存在的列,该列将其发送到“消息”输出窗格:
Msg 207,第16级,状态1,程序dbo.TestSP,第185行[Batch Start Line 2]无效的列名称'InvalidColumn'。
但是,我从代码而不是SSMS运行SP,并且没有返回任何错误或异常。
具体地说,我的Command Execute方法只是返回而不会引发异常,返回值是一个空值,因此我完全不知道记录或报告给用户的错误是什么。我也尝试过完全删除try块,结果相同。
我在VBA中使用了老式的ADODB,但是同样的原理也适用于.Net,我查看了Command对象的属性,那里似乎没有太多,返回的状态为0。
有什么方法可以在我的Command或Connection对象中的任何地方捕获或发现这些错误,以便我可以记录它们,而不仅仅是简单地说“未知错误”?
作为示例,我的存储过程如下,并且具有无效列的select语句会引发如上所示的错误,而不会引发错误。
ALTER PROCEDURE [dbo].[TestSP]
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
declare @returnCode int;
If object_id('syn_xxx','SN') is not null drop synonym syn_xxx
exec('create synonym syn_xxx for sometable')
SELECT TOP 1 InvalidColumn from syn_xxx
END TRY
BEGIN CATCH
set @returnCode=ERROR_NUMBER()
END CATCH
return @returnCode
END
我的代码是VBA,如下所示。错误集合不包含任何内容,返回值是一个空字符串。
Dim conn_ As ADODB.Connection
Dim cmd As New ADODB.Command
Set conn_ = New ADODB.Connection
conn_.Open dsn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "TestSP"
cmd.ActiveConnection = conn_
cmd.Execute
您在dsn中使用什么提供程序?
Private Sub CommandButton1_Click()
Dim con As New ADODB.Connection
Dim cmd As New ADODB.Command
Dim errLoop As ADODB.Error
Dim i As Integer
Dim StrTmp As String
'On Error GoTo AdoError
On Error Resume Next
con.ConnectionString = "Provider=SQLNCLI11;" _
& "Server=(local);" _
& "Database=master;" _
& "Integrated Security=SSPI;"
con.Open
cmd.ActiveConnection = con
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "TestSP"
cmd.Execute
MsgBox ("number of errors after procedure 'testproc' --- " & con.Errors.Count)
If con.Errors.Count > 0 Then
i = 1
' Process
StrTmp = StrTmp & vbCrLf & "VB Error # " & Str(Err.Number)
StrTmp = StrTmp & vbCrLf & " Generated by " & Err.Source
StrTmp = StrTmp & vbCrLf & " Description " & Err.Description
' Enumerate Errors collection and display properties of
' each Error object.
For Each errLoop In con.Errors
With errLoop
StrTmp = StrTmp & vbCrLf & "Error #" & i & ":"
StrTmp = StrTmp & vbCrLf & " ADO Error #" & .Number
StrTmp = StrTmp & vbCrLf & " Description " & .Description
StrTmp = StrTmp & vbCrLf & " Source " & .Source
i = i + 1
End With
Next
MsgBox (StrTmp)
End If
cmd.CommandText = "select 10 as test"
cmd.CommandType = adCmdText
cmd.Execute
MsgBox ("number of errors after 'select 10 as test' --- " & con.Errors.Count)
' Close all open objects.
If con.State = adStateOpen Then
con.Close
End If
End Sub