![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
いつもお世話になっております
古い環境なので大変恐縮ですが、行き詰ってしまったので、
ご教示いただきたいと思います。
環境:WinXP sp2
SQLServer8.0
VB6.0 sp4
VBでCSVのデータ1行について、ストアドプロシージャにて3つのテーブルに格納しようとしています。
トランザクションの管理はVB側で行っています。
1行ごとにCommitを行えば、全行格納されるのですが、
2行以上ごとにCommitを行うと、最初の1行のみが格納されないという現象がおきています。
6800行存在する同じCSVファイルについて、1行ごとにCommitを行った場合は、6800件登録されるのに
処理の最後でCommitをきった場合、6799行しか登録されません。
1行ごとにCommitをきった場合に6800行登録されるので、キー重複は考えられません。
いろいろ試してみたことを下記に書きます
結果はこのような感じです。
CASE1・・・全件登録できます
CASE2・・・2件目で重複エラーが発生します
CASE3・・・全件 - 1件が登録できます
CASE4・・・全件登録できます
CASE5・・・全件登録できます
CASE2, CASE3 で全件登録できない理由をご教示いただきたく思います。
よろしくお願いいたします。
CASE1(VBでINSERT文を記述)
localConnection.beginTrans
localConnection.execute "DELETE FROM TABLE_A"
localConnection.execute "DELETE FROM TABLE_B"
localConnection.execute "DELETE FROM TABLE_C"
FOR i = 1 to 6800
localConnection.execute "INSERT INTO TABLE_A (COL_A1, COL_A2) VALUES ('" & VAL_A1(i) & "','" & VAL_A2(i) & "')"
localConnection.execute "INSERT INTO TABLE_B (COL_B1, COL_B2) VALUES ('" & VAL_A1(i) & "','" & VAL_B2(i) & "')"
localConnection.execute "INSERT INTO TABLE_C (COL_C1, COL_C2) VALUES ('" & VAL_A1(i) & "','" & VAL_C2(i) & "')"
NEXT
localConnection.commitTrans
CASE2(ストアドプロシージャ)
localConnection.beginTrans
localConnection.execute "DELETE FROM TABLE_A"
localConnection.execute "DELETE FROM TABLE_B"
localConnection.execute "DELETE FROM TABLE_C"
' -- ストアドプロシージャのパラメータ作成
FOR i = 1 to 6800
localConnection.execute
NEXT
localConnection.commitTrans
CASE3(ストアドプロシージャ)
localConnection.beginTrans
localConnection.execute "DELETE FROM TABLE_A"
localConnection.execute "DELETE FROM TABLE_B"
localConnection.execute "DELETE FROM TABLE_C"
localConnection.commitTrans
' -- ストアドプロシージャのパラメータ作成
localConnection.beginTrans
FOR i = 1 to 6800
localConnection.execute
NEXT
localConnection.commitTrans
CASE4(ストアドプロシージャ)
localConnection.beginTrans
localConnection.execute "DELETE FROM TABLE_A"
localConnection.execute "DELETE FROM TABLE_B"
localConnection.execute "DELETE FROM TABLE_C"
localConnection.commitTrans
' -- ストアドプロシージャのパラメータ作成
localConnection.beginTrans
FOR i = 1 to 6800
localConnection.execute
localConnection.commitTrans
localConnection.beginTrans
NEXT
localConnection.commitTrans
CASE5(ストアドプロシージャ)
localConnection.beginTrans
localConnection.execute "DELETE FROM TABLE_A"
localConnection.execute "DELETE FROM TABLE_B"
localConnection.execute "DELETE FROM TABLE_C"
localConnection.commitTrans
' -- ストアドプロシージャのパラメータ作成
localConnection.beginTrans
FOR i = 1 to 6800
localConnection.execute
if i = 1 then
localConnection.commitTrans
localConnection.beginTrans
end if
NEXT
localConnection.commitTrans
A 回答 (2件)
- 最新から表示
- 回答順に表示
No.2
- 回答日時:
(今確認中かもですが)
前回の解答でも言いましたが、Case2で追うといいと思います。
理由は単純に「2回目のループで」「エラーが発生する」からです。
たとえばこんな感じのコード(これでは動かないかもですがそのあたりは適当に修正してください)で、
for i=0 to 6800
pCmd.Parameters("@i_ParamA1").Value = strVALA1(i)
pCmd.Parameters("@i_ParamA2").Value = strVALA2(i)
pCmd.Parameters("@i_ParamB2").Value = strVALB2(i)
pCmd.Parameters("@i_ParamC2").Value = strVALC2(i)
'debug(S)
Dim RS as recordset
set RS = ("Select * from tableA" の結果)
'******ブレークポイント**********
'debug(E)
localConnection.execute
next
で、上記ブレークポイントで2件目のInsert直前で
1. レコードセットRSの状態(件数が1件なのか、キー列の値は?)
2.(strVALA1(i)ではなく)pCmd.Parameters("@i_ParamA1").Valueの値
を確認した場合、「素直に考えたら」キーが重複するような状態になっているはずです。
どういう状態になっているでしょうか?
あと、エラーが発生する場合、そのメッセージはどういう形になるのでしょうか(極力正確に)
#それでもだめなら中間テーブル経由するとか代替案を考えるしかないんじゃないかと。
この回答への補足
何度も大変ご丁寧な解説ありがとうございます。
昨日、この作業を含め、いろいろ試してみました。
やはり、重複が気になったので、FOR文のカウントをそのままキーに
入れてみたり、トランザクションの分離レベルを変更したりもしました。
ご教示いただいた内容について
Executeの前後でレコードセットを調べてみました。
キー項目には、For文のカウントをCstrしてそのままキーに入れる(=重複はありえない)ようにしています。
1件目の直前ではゼロ件 / 直後で1件(1件目が正常に登録されている)、
2件目の直前では1件(1件目が正常に登録されている)
になっており、2件目のExecuteで、VB側のエラーオブジェクトが重複エラーを検出しました。
VB側エラーオブジェクト
err.Number -2147217873
err.Description PRIMARY KEY 違反、制約 'PK_TABLE_A': オブジェクト 'TABLE_A' には重複したキーは挿入できません。
もちろん、ストアドプロシージャ側でもエラーログを出力しており、
エラーがあった場合にはクライアントに返す処理も行っています
-----------------------------------------------
INSERT INTO TABLE_A
(...)
VALUES
(...)
SELECT @Error = @@Error,@ROWCOUNT = @@ROWCOUNT
if @Error != 0
BEGIN
RaisError('<%s>(%s[%s]) TABLE_Aの挿入時にエラーが発生しました。 Error=%d',10,1,@PROCEDURE_NAME,@HostName,@ApName,@Error) WITH LOG,NOWAIT
SET @o_ErrMsg = '<' + @PROCEDURE_NAME + '>TABLE_Aの挿入時にエラーが発生しました。 Error=' + @Error
GOTO ErrHandle
END
ErrHandle:
/* エラー発生 戻り値は1 */
RETURN 1
-----------------------------------------------
しかし、SQLServerのエラーログには記述されているものの、
そこからクライアントに1が返ってきているのではなく
VB側のエラーオブジェクトでした。
また、この時点で気になったのが、RS をCloseするとVB側でエラーが検出され、
RSをCloseしないと、2件目以降が正常に登録されていくということを確認しています。
トランザクションの分離レベルも、READ UNCOMMITTEDにしてみましたが、
やはり、重複エラーを返すようです。
まだ決定的ではありませんが、今のところ、下記の推測がたちました。
・beginTrans → VB側でDELETE → ストアドでINSERT → commitTrans の流れで、
DELETEが確実に行われていないのではないだろうか?
これから、他のテーブルでも同じような現象が起きるかどうかを調べてみます。
ありがとうございました。
No.1
- 回答日時:
ストアドのみで発生するということは、それに関係する部分に原因があると考えるのが自然だと思います。
たとえば、パラメータオブジェクトの値が更新されてないとか。
そのあたり記述されてないので良くわからないですが。
まず、Case2が「2件目で」重複エラーになるのが取っ掛かりになるんじゃないかと。重複しているのはどの列、どの値なのか(何件目のデータが重複しているのか)などがヒントになると重います。
デバッグ実行で、実行するタイミングでのパラメータがどうなっているかを確認すると答えになるんじゃないかと思います。
あと、ストアド実行直後に同じコネクションでレコードセットを取得して、その内容を確認すればその時点のテーブルがどういう状況下という確認はかのうですよね?そのあたり確認すれば原因がわかるのではないかと。
この回答への補足
質問が中途半端で申し訳ありません。
まず、パラメータ設定は下記のように行っています
pCmd.CommandText = "(ストアド名)"
pCmd.CommandType = adCmdStoredProc
Dim prm As New ADODB.Parameter
Set prm = New ADODB.Parameter
Set prm = pCmd.CreateParameter("ReturnVal", adInteger, adParamReturnValue)
pCmd.Parameters.Append prm
Set prm = pCmd.CreateParameter("@i_ParamA1", adChar, adParamInput, 5)
pCmd.Parameters.Append prm
Set prm = pCmd.CreateParameter("@i_ParamA2" adVarChar, adParamInput, 50)
pCmd.Parameters.Append prm
Set prm = pCmd.CreateParameter("@i_ParamB2", adVarChar, adParamInput, 50)
pCmd.Parameters.Append prm
Set prm = pCmd.CreateParameter("@i_ParamC2", adChar, adParamInput, 2)
pCmd.Parameters.Append prm
次に、Executeの直前で、下記のように設定しています
pCmd.Parameters("@i_ParamA1").Value = strVALA1(i)
pCmd.Parameters("@i_ParamA2").Value = strVALA2(i)
pCmd.Parameters("@i_ParamB2").Value = strVALB2(i)
pCmd.Parameters("@i_ParamC2").Value = strVALC2(i)
Table_A,Table_B,Table_CのPrimaryKeyはすべて、strVALA1(i)が格納されるべきCOL_A1で、
6800件について、全て重複なく、NULLでもないことを確認しています。
そのほかのA2,B2,C2についても、重複している点はみあたりませんでした。
ストアド実行直後に、イミディエイトウィンドウからコミットをかけ、
SQLServerのテーブルを見てみましたが、1件1件だと、きちんと登録されているようでした。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- PHP 重複を防ぐ記述について教えて下さい。 3 2023/04/03 14:35
- CGI perlで書いたcgiでsqliteの使い方を教えてください 2 2023/05/08 21:29
- PHP php my adminより取り出したデータ表示 2 2022/06/15 11:56
- PHP 【PHP/MySQL】コード上で生成したクエリを基に集計クエリを作りたい 1 2022/07/28 15:06
- C言語・C++・C# C++のcase文の書き方 4 2023/02/24 20:50
- PHP クエリObjectをforeachで回す時に、次のレコードへ移動せずに次のレコードを取得したい 2 2022/07/28 15:29
- MySQL SQL任意に並び替えをしたい 2 2023/08/28 10:47
- PHP PHP一覧表示した項目にリンクをはりたい 1 2023/07/12 17:08
- PHP DBのハッシュ化したパスワードをpassword_verifyで戻し照合したのですが上手く行きません 2 2023/02/06 13:24
- Ruby pandasでsqlite3にテーブル作成・追加・読み出しでindexの取り扱い方教えてください 5 2023/03/08 09:57
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
速度が低下し無効になったアド...
-
Outlook 送受信エラー
-
エクセルで個人用マクロの配布方法
-
ストアドプロシージャのネスト
-
パワーポイントのアドインのソ...
-
Word2007でアドインタブが表示...
-
ストアド内で動的にSQLを作る際...
-
エクセルのxans.について
-
エクセル・要らなくなったアド...
-
Excel:アドイン自作の方法は?
-
outlook2016のアドイン
-
ASP.netにストアドプロシージャ...
-
エクセルのショートカットメニ...
-
差し込み後、元データを変更し...
-
外部参照してるキーを主キーに...
-
エクセルVBAコードで教えて下さ...
-
フィルターかけた後、重複を除...
-
SELECT 文 GROUP での1件目を...
-
1、Rstudioで回帰直線を求める...
-
1日に1人がこなせるプログラム...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
速度が低下し無効になったアド...
-
Outlook 送受信エラー
-
エクセルのxans.について
-
広告ブロッカーのアドカードと...
-
パワーポイントのアドインのソ...
-
Excel再起動でアドインのタブが...
-
エクセルで個人用マクロの配布方法
-
ストアド内で動的にSQLを作る際...
-
Excelから自作アドインを完全に...
-
ストアドから特定のキーワード...
-
VB.NETでテキストボックスから...
-
CSVを取込むストアドプロシージ...
-
excel 複数のアドインソフトの...
-
Word2007でアドインタブが表示...
-
ストアドから得られるレコード...
-
アウトルックで、以前利用して...
-
ストアドプロシージャのネスト
-
Excelで、アドインの削除方法
-
ストアドプロシージャの条件分...
-
Excel:アドイン自作の方法は?
おすすめ情報