![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
いつもお世話になっております。
BeginTrans、CommitTrans、RollbackTransの記述位置について
お聞きしたい事があります。
合計で2のテーブルにインサート処理を行います。
Private Sub cmd_Click()
Dim strSQL AS String
'(1)adoコネクション生成
Set dbCon = Application.CurrentProject.Connection
strSQL = "テーブルAに挿入するInsert文"
'(2)テーブルaにデータ挿入
dbCon.Execute (strSQL)
'(3)テーブルaのデータをレコードセットへ
strSQL = "SELECT * FROM テーブルA"
Set dbRes = dbCon.Execute(strSQL)
Do Until dbRes.EOF
====================================================
ここでdbResの値を使用してテーブルbへ挿入するSQL文を作成
====================================================
Loop
'(4)テーブルbにデータ挿入
dbCon.Execute (strSQL)
以上の場合、テーブルaへのInsert文をCommitTransしなければ
テーブルbで使用するためデータを作成できません。
(4)でエラーが発生するとテーブルaは更新確定されているので戻り事ができないのですが
どのようにCommitTransを使用すればよろしいでしょうか??
テーブルaの挿入が失敗した場合は処理を抜けて
テーブルbの挿入が失敗した場合はテーブルaを元の状態(RollbackTrans)したいです。
ご教授お願い致しますm( _ _)m
No.7ベストアンサー
- 回答日時:
#6です
BeginTrans 等、あまりネストして使わないので間違っているかもです。
> コネクションをネストする知識が無いもので・・・
これは、コネクションのネストではなく、トランザクションのネストになると思います。
まずは、
> 多分、コネクション1つの方がネストの説明が楽だと思うので
の説明からしてみたいと思います。
以下のように1つのコネクションを2つの変数に設定した時、
各変数を用いてトランザクションを開始すると、
どの変数で開始しようとも、元のコネクションでのネストとして扱われるみたいです。
Dim cn1 As ADODB.Connection
Dim cn2 As ADODB.Connection
Set cn1 = CurrentProject.Connection
Set cn2 = CurrentProject.Connection
Debug.Print cn1.BeginTrans() ' 1 が表示
Debug.Print cn2.BeginTrans() ' 2 が表示
※ cn2.BeginTrans() で、1 にならない
これを踏まえて、以下の処理を見てみると
Set cn1 = CurrentProject.Connection
Set cn2 = CurrentProject.Connection
For i = 1 To x
cn1.BeginTrans ' ★1
cn2.BeginTrans ' ★2
For j = 1 To y
cn2.BeginTrans ' ★3
cn2.Execute "・・・・・・・"
cn2.CommitTrans '☆3
Next
cn1.Execute "・・・・・・・"
cn1.CommitTrans ' ☆2
cn2.CommitTrans ' ☆1
Next
※ ★/☆ はネストのレベル位置を示してみましたが、わかりにくいでしょうか。
この処理では、実際にはネスト2、3部分を使って処理されているように見えます。
ネスト1段削除して、For 文も削除して、変数を1つにしてみると
cn.BeginTrans ' ★1
cn.BeginTrans ' ★2
cn.Execute "・・・・・・・"
cn.CommitTrans '☆2
cn.Execute "・・・・・・・"
cn.CommitTrans ' ☆1
#6と同じ構成になりますね。
> cn.Execute "DELETE * FROM TA;"
> cn.CommitTrans: iLv = iLv - 1
> rs.Open
> DELETE * FROM TAをcn.CommitTransしているのに rs.Openできてしまうのは何故?
CommitTrans はチョッと置いておいて、
1)
cn.Execute "DELETE * FROM TA;"
rs.Open "TA", cn, adOpenForwardOnly, adLockPessimistic
は、普通にできるものと思っています。
同じコネクションを使って記述しているので、前の処理が終わらないうちに・・・・
っていう状況はないものと思っています。
DoCmd.RunSQL って使ったことありませんが、
DoCmd.RunSQL "DELETE * FROM TA;"
rs.Open "TA", cn, adOpenForwardOnly, adLockPessimistic
てなことがあったら、
DoCmd.RunSQL は、どのルートでテーブルを触りに行くのかわからないし、
いろいろと非同期という言葉も目にします。
同じコネクションを使って記述した上記 1) なら、順に処理されるものと思います。
CommitTrans はトランザクションを確定するものと思っています。
確定した後は何でもできるような気がします。
で、例を考えた時、INSERT 文を書くにはいろいろと前提条件が必要だし、
レコードをいじる・・・DELETE で良いかな・・・
当初考えたのは、
cn.BeginTrans
cn.Execute "DELETE * FROM TA;"
rs.Open "TA", cn, adOpenForwardOnly, adLockPessimistic
If (rs.EOF) Then
Debug.Print "New"
rs.AddNew
rs(1) = "ZZZZ"
rs.Update
End If
rs.Close
cn.RollbackTrans
でしたが、
> 以上の場合、テーブルaへのInsert文をCommitTransしなければ
> テーブルbで使用するためデータを作成できません。
という言葉もあって、それならって、
INSERT を DELETE に変更した手前、DELETE 部分を挟んでみました。
(INSERT と DELETE では、動きが異なるのかもしれません:この辺わかりません)
cn.Execute "INSERT INTO TA ・・・・・・;"
rs.Open "TA", cn, adOpenForwardOnly, adLockPessimistic
ってなことをやる時ありますが、おかしな動きを感じたことは今までなかったです。
(私が経験していないだけかもしれません)
また、レコードセットを得る時
> Set dbRes = dbCon.Execute(strSQL)
という記述は、ほとんどやったことが無いので rs.Open との違いはわかりません。
私がいじってみていたのは、Access2007 accdb 単体になります。
丁寧な回答、本当にありがとうございます。
感覚的にはIF文の中にIF文がある感覚でしょうか。
理解ができました、少し複雑かつ正確なプログラムが構築できそうです。
No.6
- 回答日時:
多分、コネクション1つの方がネストの説明が楽だと思うので
(私が理解している範囲になります:間違っているかも・・・・)
テスト用の環境でテーブル「TA」を作って、レコードを何件か入れておきます。
また、テーブルデザインで上から2つ目はテキスト型としておきます。
以下サンプルは、テーブル「TA」をクリアして、
テーブルが空だったらデータ1件追加します。
(この時イミディエイトウィンドウに New が表示されるはずです)
で、最後で Rollback します。
テーブル「TA」を開いてみると、元々のデータがそのままあると思います。
Public Sub Sample()
Dim cn As ADODB.Connection
Dim rs As New ADODB.Recordset
Set cn = CurrentProject.Connection
cn.BeginTrans
cn.BeginTrans ' ★
cn.Execute "DELETE * FROM TA;"
cn.CommitTrans ' ★
rs.Open "TA", cn, adOpenForwardOnly, adLockPessimistic
If (rs.EOF) Then
Debug.Print "New"
rs.AddNew
rs(1) = "ZZZZ"
rs.Update
End If
rs.Close
cn.RollbackTrans
Set cn = Nothing
End Sub
※ 最後の cn.RollbackTrans を cn.CommitTrans に変更すると、
追加した1件だけになっていると思います。(私の2007では)
※※ 上記★部分をコメントにしても、New は表示されましたけど・・・・
データ量によるものでしょうか・・・(詳しくはわかりません)
なので
> 以上の場合、テーブルaへのInsert文をCommitTransしなければ
> テーブルbで使用するためデータを作成できません。
の動作については確認してません。
バフッとしたエラー処理)
BeginTrans の戻り値は、1スタートでネスト位置を教えてくれるようです。
iLv = cn.BeginTrans()
iLv = cn.BeginTrans()
とすると、1回目は iLv = 1 に、2回目は iLv = 2 に
そこで、CommitTrans / RollbackTrans 時に iLv = iLv - 1 してあげれば
ネスト位置がわかると思います。
途中エラーがあったら、iLv = 0 になるまで RollbackTrans するとか・・・
Public Sub Sample()
Dim cn As ADODB.Connection
Dim rs As New ADODB.Recordset
Dim iLv As Long
iLv = 0
Set cn = CurrentProject.Connection
On Error GoTo ERR_HND
iLv = cn.BeginTrans()
iLv = cn.BeginTrans()
cn.Execute "DELETE * FROM TA;"
cn.CommitTrans: iLv = iLv - 1
rs.Open "TA", cn, adOpenForwardOnly, adLockPessimistic
If (rs.EOF) Then
Debug.Print "New"
rs.AddNew
rs(1) = "ZZZZ"
rs.Update
End If
rs.Close
cn.RollbackTrans: iLv = iLv - 1
ERR_EXIT:
Set cn = Nothing
Exit Sub
ERR_HND:
While (iLv > 0)
cn.RollbackTrans: iLv = iLv - 1
Wend
Resume ERR_EXIT
End Sub
ご返答ありがとうございます。
コネクションをネストする知識が無いもので・・・
とても基本的な話で申し訳ないのですが
cn.Execute "DELETE * FROM TA;"
cn.CommitTrans: iLv = iLv - 1
rs.Open
DELETE * FROM TAをcn.CommitTransしているのに
rs.Openできてしまうのは何故でしょう・・・?
No.5
- 回答日時:
以下のような感じでは?
Set dbCon1 = Application.CurrentProject.Connection
Set dbCon2 = Application.CurrentProject.Connection
On Error Goto ER_Shori_1
dbCon1.BeginTrance
'(2)テーブルaにデータ挿入
'テーブルaの挿入が失敗した場合は処理を抜けて
dbCon1.Execute (strSQL)
dbCon1.ComitTrance
On Error Goto 0
On Error Goto ER_Shori_2
dbCon2.BeginTrance
Do Until dbRes.EOF
====================================================
ここでdbResの値を使用してテーブルbへ挿入するSQL文を作成
====================================================
Loop
'(4)テーブルbにデータ挿入
dbCon2.Execute (strSQL)
dbCon2.ComitTrance
dbCon_Exit:
Set dbCon1 = Nothing
Set dbCon2 = Nothing
ExitSub
ER_Shori_1:
dbCon1.Rollback
Resume dbCon_Exit
ER_Shori_2:
dbCon2.Rollback
Resume dbCon_Exit
回答ありがとうございます。
ER_Shori_2でdbCon2.Rollbackすると
(2)テーブルaにデータ挿入は既にコミットされているように見えるのですが
テーブルaは元の状態にロールバックしてくれるのでしょうか??
No.2
- 回答日時:
ご返答ありがとうございます。
Connectionを2つ作成して入れ子にするやり方でしぃうか。
知らない技術でした、勉強になりました。
ありがとうございます。
No.1
- 回答日時:
状況によりますが、一般的には、
On Error Goto ER
・
・
dbCon.BeginTrance
dbCon.Execute (strSQL)
・
・
・
(4)テーブルbにデータ挿入
dbCon.Execute (strSQL)
dbCon.ComitTrance
・
・
ER:
dbCon.Rollback
のような感じですが。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
「どうして捨てられないの?」前妻の物を捨てられない男性の心理って?
前妻の物を捨てられない理由に加え、捨てるための手段はあるのかを専門家に聞いてみた!
-
AccessのDAO.ExecuteとDoCmd.RunSqlの違いについて
その他(データベース)
-
「RunSQL」と「Execute」の違い
Access(アクセス)
-
Access フォームのテキストボックスに半角英字のみで入力する設定は
Access(アクセス)
-
-
4
Access サブフォームでの選択行の取得
その他(データベース)
-
5
SELECTした結果に行番号を求めたい
PostgreSQL
-
6
ADOを使ったDBアクセス後のメモリ解放
その他(データベース)
-
7
Access VBA DB(先頭の0値を消す方法)
PowerPoint(パワーポイント)
-
8
OR関数
その他(Microsoft Office)
-
9
Accessのフォームにて、詳細行のボタンを行の内容により、表示/非表
その他(Microsoft Office)
-
10
YES/NO型の値
Excel(エクセル)
-
11
accessでレコード更新直後の反映について
その他(データベース)
-
12
フォームの高さを数値で指定したいのですが
Excel(エクセル)
-
13
VBA テキストボックスを選択状態にしたい
その他(プログラミング・Web制作)
-
14
【DB】同じトランザクション内でupdateとselectをしたときの結果値
その他(データベース)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
CSVファイルのエクスポートでソ...
-
手動または分散トランザクショ...
-
Excel複数シートをaccessへ一括...
-
Access2007でアプリケーション...
-
VB.NET コマンドの使い回しに問...
-
VB.NETからAccess内のデータベ...
-
ワークテーブルの作成について
-
AccessからExcelへエクスポート...
-
VBとアクセスでSQL文に変...
-
ロケールに対応するストリング...
-
COBOLのINVALID KEYが理解でき...
-
オラクルデータベースへの更新方法
-
.net 複数の主キーを設定する方法
-
ExcelVBAからAccessMDB内のテー...
-
【ADO】「Execute」を使うと...
-
VB.NET データセットとADOレコ...
-
エクセルのテーブルを解除する...
-
Accessで別mdbのテーブルをコピー
-
DAOでフィールドのデータ型を変...
-
他のMDBのテーブルに追加したい
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBとアクセスでSQL文に変...
-
『列名 '担当者CD' があいま...
-
AccessからExcelへエクスポート...
-
他のMDBのテーブルに追加したい
-
Accessで別mdbのテーブルをコピー
-
手動または分散トランザクショ...
-
DataGridViewに複数テーブルの...
-
エクセルのテーブルを解除する...
-
ACCESS2010 実行時エラー 2766
-
SQLを発行とは?クエリの作成と...
-
COBOLのINVALID KEYが理解でき...
-
アクセステーブル、リンクとロ...
-
CSVファイルのエクスポートでソ...
-
HTMLのテーブルの行数が多くな...
-
ExcelVBAからAccessMDB内のテー...
-
DataGridの中身をDataSetにテー...
-
ACCESSのテーブル名をリストに...
-
access2007 「#Deleted」
-
.net 複数の主キーを設定する方法
-
DAOでフィールドのデータ型を変...
おすすめ情報