仕事を頑張る人のおしりトラブル対策

Microsoft Visual Basic 2010 Express の質問です。

ExcelVBAや、AccessVBAで作成したプログラムを、VBに移そうと思っています。

ネットや本のサンプルを、自分のやりたいことに修正しつつ、一応、動作としては希望通りなのですが、元々VBAで簡易に作ったものだけに、本来なら注意すべきインスタンスの管理などがおざなりになっています。

動作は一応正常ですが、果たしてこれで良いのか不安でもありますので質問させていただきます。


大抵の本やサンプルには、複数のSQLを連続で発行するようなものは載っていませんが、いくつものSQLを順次発行していく処理をする時は、どのように記述するのが正しいでしょうか?

例えば、Access2010データベース、C:\test.accdb には、別のテーブルからリンクしたテーブル genpon があるとします。これをコピーしたテーブル、tb01を作る場合、

------------------------------------
Dim com As OleDb.OleDbCommand
Dim cn As OleDb.OleDbConnection = New OleDb.OleDbConnection( _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=C:\test.accdb;")

cn.Open()

''現在のデータを削除
com = New OleDb.OleDbCommand("DROP TABLE [tb01];", cn)
com.ExecuteNonQuery()

''現在のデータを削除
com = New OleDb.OleDbCommand("SELECT * INTO [tb01] FROM [genpon];", cn)
com.ExecuteNonQuery()

------------------------------------

SQLとしては、現テーブルをDROPして、SELECT * INTO を発行すれば希望通りで、上記もその通り動きますが、NEWでインスタンス作成を繰り返しているのは、やってはいけない事ではないでしょうか?


さらに、例えばこのコードの続きとして、FOR~NEXTや、DO~LOOPで繰り返しを設け、その中でINSERT INTO を発行しながら、データを登録するような処理を加える場合、このままでは NEWをループの回数分、繰り返す事になります。

プロシージャの中で、ループなどで複数のSQLを発行する場合、記述として正しい作法がありましたら、教えてください。

このQ&Aに関連する最新のQ&A

A 回答 (1件)

それぞれの最後、つまりExecuteNonQuery()の発行後、Dispose()すれば問題ありません。


が、どうせ同じインスタンスを利用するならば、2回目以降はCommandTextプロパティに設定されている
クエリを変更して発行、その後Dispose()でも良いでしょう。

また、移行ということで、元々問題ないのでしょうが、問題があるようならば
プリペアドステートメントによる発行を推奨します。(SQLインジェクション対策)
Accessはクエリキャッシュ機構はないでしょうから、パフォーマンスは変わらないでしょうけど。
http://msdn.microsoft.com/ja-jp/library/vstudio/ …(v=vs.100).aspx
    • good
    • 0
この回答へのお礼

ありがとうございます。

Dispose() を発行後にセットする事にしました。

大きなやり方の間違いでなくて、ホッとしています。

お礼日時:2014/04/10 10:40

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q複数SQL発行について

お世話になります。

VB.NET2003とSQLServer2005にて開発を行っております。

Aテーブルからデータを取得してその取得データを元にBテーブルを参照する。
と、言うのがあるのですが、
Bテーブル参照時に「この接続に関連付けられている DataReader が既に開いています。この DataReader を最初に閉じる必要があります。」の
エラーとなってしまいます。

複数SQLを発行する場合、再度接続を行わなければならないのでしょうか?
同一接続内で複数のSQLを発行することは出来ないのでしょうか?

どなたかご存知でしたらお教え願います。

以下、ソース

' 変数宣言
Dim objDBConnect As SqlConnection
Dim objDBTran As SqlTransaction
Dim objSqlCmd As SqlCommand
Dim objSqlDRA As SqlDataReader
Dim objSqlDRB As SqlDataReader

' データベース接続
objDBConnect = New SqlConnection("接続文字列")
objDBConnect.Open()

' トランザクション開始
objDBTran = objDBConnect.BeginTransaction(IsolationLevel.ReadCommitted)

' SQL発行
objSqlCmd = New SqlCommand("SELECT * FROM A_TABLE", objDBConnect)
objSqlDRA = objSqlCmd.ExecuteReader()

While objSqlDRA.Read()

objSqlCmd = New SqlCommand("SELECT * FROM B_TABLE", objDBConnect)
objSqlDRB = objSqlCmd.ExecuteReader() ←ここで、エラーとなってしまいます。

End While

お世話になります。

VB.NET2003とSQLServer2005にて開発を行っております。

Aテーブルからデータを取得してその取得データを元にBテーブルを参照する。
と、言うのがあるのですが、
Bテーブル参照時に「この接続に関連付けられている DataReader が既に開いています。この DataReader を最初に閉じる必要があります。」の
エラーとなってしまいます。

複数SQLを発行する場合、再度接続を行わなければならないのでしょうか?
同一接続内で複数のSQLを発行することは...続きを読む

Aベストアンサー

#1です。
ごめんなさい。1接続に対して1つだけみたいです。

▼MSDN引用
DataReader の終了
DataReader を使い終えたら、Close メソッドを呼び出す必要があります。

Command に出力パラメータや戻り値が含まれていても、DataReader が終了するまでは使用できません。

DataReader が開いている間、Connection はその DataReader によって排他的に使用されています。元の DataReader が終了するまでは、その Connection に対してはどのコマンドも実行できません。別の DataReader を作成することもできません。

参考URL:http://msdn2.microsoft.com/ja-jp/library/haa3afyz.aspx

Q一つのトランザクションでSELECTとUPDATEできますか? (ADO.NET)

いつもお世話になっております。

ADO.NETの話なのですが、トランザクションを開始したコネクションオブジェクトで
DataAdapterを使ったSELECTと、ExecuteNonQueryを使ったUPDATEを交互に繰り返し
行うことはできるでしょうか?

現状できていないので可能なのであれば共通関数の見直しが必要かと思っています。
いまはSELECTとUPDATEを別のコネクションで行っているのですが、UPDATE後に
同じテーブルの該当レコードをSELECTにいくため、デッドロックが発生しています。

Aベストアンサー

>それにしてもコネクションとトランザクションオブジェクトを別々に
>渡してやる必要性がよく理解できません。コネクションオブジェクトから
>トランザクションオブジェクトも参照できるのでは?と思うのですが・・・。

たしかに私も腑に落ちない・・・気がします
なにか別に設定が必要な理由があるのかも知れませんね
複数のトランザクションが存在する場合に指定が必要になるのかも!

私の過去のコードにはしっかり
sqlCommand.Transaction = tran
がありました(いつの間にか記述してたみたい)
すいません。#2ではまったくその事に触れていませんでした

憶測での回答になってしまいますが
トランザクションが割り当てられたコマンドが実行されたときに
自動的にBegin Tranされ
トランザクションが割り当てられていないコマンドが実行されたときに
自動的にCommit Tranが実行されてしまうのかも知れません
時間があったら実証して見たいと思います

QSQLで特定の項目の重複のみを排除した全項目を取得する方法

私は仕事上でデータベースを扱っていて、タイトルのような処理を行う必要があるのですが、いかんせん方法がわからずネット上を検索しても同様だったためここで質問させていただきます。

質問点を簡単に説明いたしますと、
たとえばAというテーブルがあって、

項目名1 項目名2 項目名3 項目名4
 A    あ    ア    亜
 A    い    ア    以
 A    う    ア    宇
 B    え    イ    江
 B    お    イ    尾

上のような構造になっている場合に「項目名1」について重複している項目を排除し、結果として


項目名1 項目名2 項目名3 項目名4
 A    あ    ア    亜
 B    え    イ    江

上のようなデータを取得したいのです。
この時に、Aの重複を排除して取得するレコードは1~3行目のどれでもよいです。
また、データを取得する際には必ずそのレコードの「全項目」を取得したいのでDistinctはうまく使えませんでした。

どなたか詳しい方、方法を教えてくださると幸いです。回答お待ちしております。

私は仕事上でデータベースを扱っていて、タイトルのような処理を行う必要があるのですが、いかんせん方法がわからずネット上を検索しても同様だったためここで質問させていただきます。

質問点を簡単に説明いたしますと、
たとえばAというテーブルがあって、

項目名1 項目名2 項目名3 項目名4
 A    あ    ア    亜
 A    い    ア    以
 A    う    ア    宇
 B    え    イ    江
 B    お    イ    尾

上のよ...続きを読む

Aベストアンサー

比較可能で一意性のある値をもてる項目6をテーブルに追加して、

select T.* from T, (select Item1,min(Item6) as Item6 from T group by item1) W where T.item6=W.item6;

――ってやるのが、一番手っ取り早いと思います。
他のところに影響がでないのであればですが。
oracleならrowidを使うとか、レコードの更新時刻を突っ込むとか。

Q3つの表の外部結合

表A、B、Cの3つがあり、Aのすべての行を出力したいと考えています。
外部結合を用いるのだとは思うのですが、3つの表に対して行う場合の
書き方がわからず困っています。
ご教授いただけないでしょうか?
select * from a,b,c
where a.商品ID =b.商品ID (+) and b.商品ID (+) =c.商品ID (+)
としてみましたが、うまくいきませんでした。

Aベストアンサー

ansi構文の趣旨からいえば、結合条件と絞り込み条件は分けて書くので・・

select *
from a
left join b on (a.商品ID =b.商品ID)
left join c on (b.商品ID =c.商品ID)
where a.年月 = 任意の値

と書くのが一般的でしょうね。

QDataGridViewで指定したセルの値を取得

こんにちは。

VB2008のDataGridViewで指定したセルの値を取得をする方法がわかりません。
どなたか教えてください。

Aベストアンサー

こんばんは.

 Dim Data As String
 Data = Me.DataGridView(0, 2).Value
 MsgBox(Data)

みたいな感じで取れないですかね???

QMAX値を条件にデータを取得するには?

SQL文で困っています。
ご教授下さい。


下記のようなデータがあった場合、それぞれの区分毎に
年月が最大(最新)のデータを取得したいです。
(実際には1レコードにその他項目があり、それらも取得します。)
<検索対象データ>
区分 年月   金額
-----------------------------
A   200412  600
A   200503  560
B   200311  600
B   200508  1000
B   200504  560
C   200508  400
C   200301  1100


<取得したいデータ>

区分 年月   金額
-----------------------------
A   200503  560
B   200508  1000
C   200508  400

よろしくお願いします。

Aベストアンサー

テーブル名をXXXとすると次のようなSQLでよいと思います。(最善の方法かどうかは自信がないですが)

select B.* from (select 区分, max(年月) as 年月 from XXX group by 区分) As A
inner join XXX as B on A.区分 = B.区分 and A.年月 = B.年月
order by B.区分

Q複数のクエリーをVBで書く方法を教えてください。

4つのテーブルから各々2つのクエリーを作り、その2つのクエリーから1つのクエリーを作り最終的に1つのrecordsetを抽出するという作業をVBで書きたいのですが、最初の2つのクエリーのrecordsetは取得できますが、そのrecordsetを使った最終クエリーがうまく動いてくれません。サンプルとしてどういう風に構文にしたらいいか、だれか教えてgoo?ちなみに超初心者なので、わかりやすくお願いします。

Aベストアンサー

VBによるSQLの結果の取得について勘違いされているようなので最初から整理します。

1.SQL文は、VBの文字列である必要があります。
2.SQL文の中で使用するフィールド名、テーブル名は、実際のデータベースに存在する必要があります。
3.1度のSELECT文の発行で、1つのRecordsetのみ取得することができます。

です。

>rs1は複数件の結果を返します。
ということは、3に引っかかりますよね。
つまり、考えられる組み合わせの回数分SELECT文を発行してRecordsetを取得する必要があります。


>それと副問合わせというものはどういうことですか?
副問い合わせというのは、1つのSQLの中でSELECT文で抽出した結果を使用して別の結果を取得したりレコードを更新したりすることです。

詳しくはこちらをどうぞ。
http://www.atmarkit.co.jp/fnetwork/rensai/sql07/sql1.html

ただし、今回のようにテーブル名やフィールド名が格納されているテーブルの内容を元に副問い合わせを行うことはできません。

VBによるSQLの結果の取得について勘違いされているようなので最初から整理します。

1.SQL文は、VBの文字列である必要があります。
2.SQL文の中で使用するフィールド名、テーブル名は、実際のデータベースに存在する必要があります。
3.1度のSELECT文の発行で、1つのRecordsetのみ取得することができます。

です。

>rs1は複数件の結果を返します。
ということは、3に引っかかりますよね。
つまり、考えられる組み合わせの回数分SELECT文を発行してRecordsetを取得する必要があります。


>...続きを読む

QSQLの速度をあげるには・・・

テキストファイルからキーワードを拾って
SQLをなげています
SQLの質問になってしまうかもしれません
いまはADO接続でやっています

Open ファイル as input......

SQL = select * from tbl where name like '%キーワード%'
execute(SQL)

レコードセットの値で処理をいろいろ・・・
Loop

もともとのDBの件数がものすごくおおくてselect文に結構な時間が
かかってしまいます。速度をあげるほうほうってあるのでしょうか
私にはおもいつかなくて・・・

こういったほうほうは どう? ってのがありましたら
おしえていただきたいのですが よろしくおねがいします。

Aベストアンサー

確かに・・・Like演算子・・・あまり使いたくないですね・・・
文字列比較は処理を遅くさせるし、増してや「=」ではなくLikeですから、膨大な時間がかかる恐れが・・・

ちなみにぼく自身、DB系を多くしています。今の仕事もDB系なのですが、元となるホストは他の会社が行っており、それにあわせて作らなければなりません。
で、そのホスト連携部分に文字列を比較しなければならない部分があるんですよ・・・・
自分の会社ならまだしも、他の会社がすでに設計済みのDBだから変えようがないのです。。。

まぁ愚痴っても仕方ないか・・・


なのでぼくも(不本意ながら)Like演算子を使用しています。


長い前置きはさておき・・・

本題のSQLのスピードなのですが、
http://homepage2.nifty.com/inform/vbdb/addnew.htm
こちらに面白い記述がありました。

AddNewにかかるスピードの検証で
Access データベースの場合: AddNew のほうが INSERT INTO より5倍以上速い
SQL Server の場合: INSERT INTO のほうが AddNew より 1.4倍 くらい速い
とあります。


たぶんで物を言ってはいけないと思うけど、言っちゃいます。

(1)もしDBがアクセスで
 >レコードセットの値で処理をいろいろ・・・
 のところがUpdate用のSQL文で処理を行ってる場合

 Recordsetをして、処理を行う


(2)もしDBがアクセス以外で
 >レコードセットの値で処理をいろいろ・・・
 のところがRecordsetで処理を行ってる場合

 Recordsetをせずに、UPDATE用のSQLを実行する


未検証なのですが多分イメージとして、こういうパターンが各DBに適してるのかな?

すでにこのパターンなのであれば、意味ないですね(^^;)

参考URL:http://homepage2.nifty.com/inform/vbdb/addnew.htm

確かに・・・Like演算子・・・あまり使いたくないですね・・・
文字列比較は処理を遅くさせるし、増してや「=」ではなくLikeですから、膨大な時間がかかる恐れが・・・

ちなみにぼく自身、DB系を多くしています。今の仕事もDB系なのですが、元となるホストは他の会社が行っており、それにあわせて作らなければなりません。
で、そのホスト連携部分に文字列を比較しなければならない部分があるんですよ・・・・
自分の会社ならまだしも、他の会社がすでに設計済みのDBだから変えようがないのです。。。

...続きを読む

Q日付型カラムへのデータINSERT

お世話になります。ひとつご教授ください。

オラクル10g, ojdbc14でjdk1.4.2から接続です。

INSERT命令を使ってテーブルにレコードを追加する際に、DATE型のカラムに対して

INSERT TABLE_A (DATE1, ...) VALUES ('2006-4-27 12:00:00', ...);

を実行するとエラーORA-01861が出ます。そこで

INSERT TABLE_A (DATE1, ...) VALUES ('2006-4-27', ...);

このように記述して再度実行すると通ります。

このようなとき、時間の部分まで設定した値をカラムに格納したいときはどうしたらよろしいでしょうか?

よろしくお願いします。

Aベストアンサー

ごめんなさい。
説明と文例が違ってしまいました。
正しくはこちらです。

INSERT TABLE_A (DATE1, ...) VALUES (to_date('2006-4-27 12:00:00','yyyy/mm/dd hh24:mi:ss'), ...);
というように、to_date関数を使うのが一般的かと思います。

QUPDATE文のWHERE条件に他のテーブルのフィールドも入れたい

SQL文についてです。

表Aで列1と列2が'◎'のものについて、列3,列4,列5をそれぞれ'○','△','×'に更新したい場合は下記でOKだと思います。
UPDATE 表A
SET 列3 = '○', 列4 = '△', 列5 = '×'
WHERE 列1 = '◎' AND 列2 = '◎'

列1と列2をキーとして表Aと結合できる表Bが存在するとします。
条件に表Bの列6が'□'だった場合を追加したい時、どのような方法で行えば良いのでしょうか?
内部結合やWHERE EXISTSなどをいろいろ調べたのですが、SQL文に慣れていないためかうまくいきません。
初歩的な質問で申し訳ありませんが過去質問で参考になるものがなかったのでお願いします。

Aベストアンサー

UPDATE 表A
SET 列3 = '○', 列4 = '△', 列5 = '×'
WHERE 列1 = '◎' AND 列2 = '◎'
AND EXISTS
( SELECT 1 FROM 表B
WHERE 表B.列1 = 表A.列1
AND 表B.列2 = 表A.列2
AND 表B.列6 = '□' )
じゃだめですか。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報