
いつもお世話になっております。
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で質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) ExcelからAccessのテーブルに書き込む時に時間がかかる 1 2022/10/14 20:38
- その他(データベース) pythonでsqlight勉強中、クエリー結果の利用法教えて下さい 1 2022/04/28 20:38
- Access(アクセス) access,vbaでフォルダ内のファイルをテーブルにインポート、ファイル名もフィールドに追加したい 1 2022/08/31 11:11
- Oracle SQL update方法 2 2022/06/22 14:07
- Access(アクセス) アクセス テーブルの空白を変数に置換するボタンが作りたい 4 2022/07/08 11:19
- MySQL 複数DBテーブルからのデータ取得 3 2022/05/17 15:02
- Visual Basic(VBA) access count数を変数に格納 2 2022/03/30 19:21
- その他(データベース) 更新クエリをリンクデータベーステーブルに実行し実行時エラー3362固有インデックスに重複する値が含ま 1 2022/09/21 11:44
- Ruby pandasでsqlite3にテーブル作成・追加・読み出しでindexの取り扱い方教えてください 5 2023/03/08 09:57
- PHP 【PHP/MySQL】コード上で生成したクエリを基に集計クエリを作りたい 1 2022/07/28 15:06
このQ&Aを見た人はこんなQ&Aも見ています
-
Accessdでの「トランザクションが多すぎる」エラーとは何?
その他(データベース)
-
「RunSQL」と「Execute」の違い
Access(アクセス)
-
access adoのトランザクション
Visual Basic(VBA)
-
-
4
レコードを保存するコード アクセスvba
その他(Microsoft Office)
-
5
Access レコード削除時に「カレントレコードがありません」エラーが表示されてしまう
Access(アクセス)
-
6
ACCESS 複数のフォームから同一テーブル参照
Access(アクセス)
-
7
Access サブフォームでの選択行の取得
その他(データベース)
-
8
Access 別フォームへの再クエリ(更新)がしたい。
その他(データベース)
-
9
ACCESS2007 VBA 「INSERT INTO~」について
PowerPoint(パワーポイント)
-
10
サブフォームの行ごとにコンボボックスの表示項目を変更する方法が知りたいです
Visual Basic(VBA)
-
11
テーブルに主キーを作らないデメリットは?
その他(Microsoft Office)
-
12
親フォームからサブフォームのレコードソースを設定
Access(アクセス)
-
13
Access VBAから使用したExcelプロセスを閉じる方法について
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ASP.NET GridView 一致した行の...
-
ExcelからAccessのテーブルに書...
-
他のMDBのテーブルに追加したい
-
『列名 '担当者CD' があいま...
-
html javascriptにてWeb SQLを...
-
ロケールに対応するストリング...
-
VBとアクセスでSQL文に変...
-
エクセルのテーブルを解除する...
-
[C#] DataGridViewでコンボボッ...
-
【ADO】「Execute」を使うと...
-
オラクルデータベースへの更新方法
-
ACCESSのテーブル名をリストに...
-
複数のデータベースを検索したい
-
VBAで OLEオブジェクト型のフ...
-
DataGridViewに複数テーブルの...
-
Accessで別mdbのテーブルをコピー
-
MySql PHP 2つのテーブルをJOI...
-
DataGridViewで変更した値を反...
-
jquery 複数のテーブルを合わせ...
-
★クリスタルレポートの元になる...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
『列名 '担当者CD' があいま...
-
SQLを発行とは?クエリの作成と...
-
手動または分散トランザクショ...
-
VBとアクセスでSQL文に変...
-
AccessからExcelへエクスポート...
-
Accessで別mdbのテーブルをコピー
-
エクセルのテーブルを解除する...
-
CSVファイルのエクスポートでソ...
-
COBOLのINVALID KEYが理解でき...
-
ExcelVBAからAccessMDB内のテー...
-
ACCESS2010 実行時エラー 2766
-
.net 複数の主キーを設定する方法
-
ExcelからAccessのテーブルに書...
-
アクセステーブル、リンクとロ...
-
Access2007でアプリケーション...
-
他のMDBのテーブルに追加したい
-
DAOの作成単位について
-
Excel複数シートをaccessへ一括...
-
[C#] DataGridViewでコンボボッ...
-
リストボックスに複数列表示し...
おすすめ情報