さまざまなテーブルにいくつかのトリガーがあり、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