こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

PostgreSqlのテーブルをVBから更新

PostgreSqlのテーブルをVBから更新

【テーブル】
tbl1 (
item1 integer not null, -- 数値:ユニークキー
, item2 character varying, -- 文字
, item3 timestamp without time zone -- タイムスタンプ
, CONSTRAINT tbl1pk PRIMARY KEY (item1)
)

【仕様】
1.テーブル内の特定の1レコードを取得

2.取得したレコードをVBの画面に表示

3.入力:VBの画面で item2 の表示内容を変更

4.ボタン入力
4-1.レコードが存在しない場合
 メセージボックスに「誰かが消した」と表示

4-2.タイムスタンプに変化がある場合
 メセージボックスに「誰かが変更した」と表示

4-3.タイムスタンプに変化がない場合
 Updateする。


【前提】
普通にアップデートするだけなら、下記でできました。

Private DateTime1 As DateTime ' 画面表示の時に取得したitem3の値が入っているとする
 :
 :
Dim NpgsqlConnection1 As NpgsqlConnection = New NpgsqlConnection
Dim NpgsqlCommand1 As NpgsqlCommand = New NpgsqlCommand

NpgsqlCommand1 = NpgsqlConnection1.CreateCommand
NpgsqlCommand1.CommandText = "update tbl1 " _
& "set item2 = '" & Me.TextBox1.Text & "'" _
& ", item3 = current_timestamp " _
& "where item1 =" & キー値
NpgsqlConnection1.ConnectionString = 接続情報

NpgsqlConnection1.Open()
NpgsqlCommand1.ExecuteNonQuery()
NpgsqlConnection1.Close()


【考察】
変更された場合は、更新対象外にするのは、条件に入れればなんとかなります。

NpgsqlCommand1.CommandText = "update tbl1 " _
& "set item2 = '" & Me.TextBox1.Text & "'" _
& ", item3 = current_timestamp " _
& "where item1 =" & キー値 _
& "and date_trunc('second', item3) =" & "to_timestamp('" & Format(DateTime1, "yyyy-MM-dd HH:mm:ss") & "', 'YYYY-MM-DD HH24:MI:SS')"

しかし、これではこのSQLで更新されたのか、他で更新があったためにスキップしたのかが分かりません。

直前のSQLで更新があったかどうか、もしくは何件更新対象になったかを得る事はできませんか?


もしくは、
一旦呼び出してロックし、その間にタイムスタンプを取り出し、
Vb内に持っていた前回のタイムスタンプと比較し、同じであれば更新する。
同じでなければステータスを返す。
というふうにしたいです。



【質問】
アップデート文で更新対象になった件数を取得する事はできませんか?


もしくは、フェッチの方法を教えて下さい。
上記の仕様のようにタイムスタンプを判断し、そのレコードを掴んだままアップデートしたいなら、フェッチするしかないのかと思っています。
でも、そのやり方が分かりません。

・コネクト
・カーソル定義
・カーソルオープン
・ネクストレコード
・レコードを取得し、VB側のタイムスタンプと比較←どうやって?
・カーソル行に対しアップデート
・レコードの終わり
・0件なら「誰かが消した」と表示
・カーソルクローズ
・コネクト解除

やりたい事は上記でSqlもVbも分かるのですが、インターフェイス込みでコマンドレベルの方法が分かりません。

フェッチでの方法が分からないので教えて下さい。

フェッチで以外の方法で同等の事が出来るもっと良いやり方があれば教えて下さい。


以上、よろしくお願いします。

投稿日時 - 2013-12-03 09:40:44

QNo.8371368

すぐに回答ほしいです

質問者が選んだベストアンサー

> Npgsqlではフェッチは使えないのでしょうか?
できますよ。
http://msdn.microsoft.com/ja-jp/library/9kcbe65k(v=vs.110).aspx

別にNpgsqlに限った話ではなく、こういうライブラリはよっぽど独自
実装してない限り、大抵DbCommand、DbDataReaderを使うのと一緒です。

継承元クラスを直接利用するならば、
Dim con As NpgsqlConnection ' コネクションがある前提
Dim command As NpgsqlCommand = con.CreateCommand()
Dim r As NpgsqlDataReader = command.ExecuteReader()
Do While r.Read()
 Console.WriteLine(r.GetString(0))
Loop
r.Close()
command.Dispose()

こんな感じに。

DB操作がわからないなら、System.Data.Common内のクラスを見るなり、
それぞれのメソッドを見るなり、他サイトでクラスやメソッド単位で調べるなり
すれば解決すると思います。
Npgsqlのクラスのほとんどは、このクラスを継承して実装が行われています。
http://msdn.microsoft.com/ja-jp/library/System.Data.Common(v=vs.110).aspx

Npgsqlのクラス名を知りたければ、CHMファイルがあります。
http://pgfoundry.org/frs/?group_id=1000140

投稿日時 - 2013-12-03 16:27:42

ANo.3

このQ&Aは役に立ちましたか?

14人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.2

ExecuteNonQuery()は、影響を受けた行数を返すと思いますが。
http://msdn.microsoft.com/ja-jp/library/system.data.sqlclient.sqlcommand.executenonquery(v=vs.110).aspx

キー情報、タイムスタンプを条件に加えた状態でUPDATEを走行させた時、
タイムスタンプが同一ならば1が返されるでしょうし、異なれば
0となるでしょう。

また、存在するかどうかということは上記だけでは分からないので、
SELECTする必要があるでしょう。

ざっくりとした手順としては以下のようになると思います。
画面表示時
 1.SELECTして画面を表示。タイムスタンプも保持する。

更新時
 1.トランザクション開始
 2.タイムスタンプを条件に含まず、行ロックでSELECTして情報を取得。
   情報が取得できないならば『誰かが消した』。
 3.タイムスタンプも条件に含んで、UPDATEする。
   影響結果が0なら『誰かが変更した』、1なら『更新した』
 4.COMMIT

投稿日時 - 2013-12-03 10:33:33

お礼

ありがとうござます。

Npgsqlではフェッチは使えないのでしょうか?

投稿日時 - 2013-12-03 14:15:02

ANo.1

> アップデート文で更新対象になった件数を取得する事はできませんか?
ExecuteNonQueryメソッドの説明をよく読んでくださいな。
http://www.postgresql.jp/document/NPGSQL/api/Npgsql.NpgsqlCommand.ExecuteNonQuery.html

投稿日時 - 2013-12-03 10:03:56

お礼

ありがとうござます。
よく読んでみました。
戻り値がそうだったのですね。

投稿日時 - 2013-12-03 13:52:01

あなたにオススメの質問