5

さまざまなテーブルにいくつかのトリガーがあり、raiserrorを使用して、ユーザーが何か悪いことをしようとしたことをユーザーに通知します。いくつかの挿入と更新をアトミックに実行し、トリガーの1つがそう言った場合はロールバックしたいと思います。私は前世で悪かったので、AccessVBAを使用しています。

最初のステートメントに誤りがあると、VBAで実行時エラーが発生します。ただし、2番目以降のステートメントがraiserrorを呼び出す場合、エラーメッセージは表示されません。

解決策:connection.Errorsコレクションを調べます。

これは、Access2007ADPフロントエンドおよびSQL2005データベースです。

以下の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
4

2 に答える 2

3

http://support.microsoft.com/kb/254304を参照してください

PRB:ADOエラーコレクションにユーザー定義のエラーメッセージが含まれていない

ActiveXデータオブジェクト(ADO)を使用してSQL Serverストアドプロシージャ(SP)を実行しても、接続オブジェクトのADOエラーコレクションに、SPで発生するユーザー定義のエラーが入力されません。この動作は、SQLServer用のOLEDBプロバイダー(SQLOLEDB)を使用してSQLServerデータベースへのADO接続を確立する場合にのみ発生します。

SQLスクリプトの先頭で明示的にnocountをオンに設定する必要があります。

于 2012-10-17T18:12:29.930 に答える
1

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
于 2012-05-14T11:18:00.083 に答える