DOBON.NET DOBON.NETプログラミング掲示板過去ログ

SQLServerのテーブルで、INSERTした行のみの内容を、UPDATEするには。

環境/言語:[XP、VB.NET2003]
分類:[.NET]

お世話になります。
以下、ご質問させて頂きます。

MicrosoftSQLServerのデータベースに、2つのテーブルがあります。

(テーブル名)
T_FROM
(フィールド)
FROMID(主キー、オートナンバー)
数値(数値型)

(テーブル名)
T_TO
(フィールド)
TOID(主キー、オートナンバー)
数値1(数値型)
数値2(数値型)
数値3(数値型)

移行ボタン(btnIko)をクリックすると、
T_FROMの[数値]に入っている数値を、上から順番に、
T_TOの[数値1]〜[数値3]に、移行していきたいと、考えております。

例えば、

T_FROM
数値
1
2
3
4
5

と、入っている場合、

T_FROM
数値1 数値2 数値3
1 2 3
4 5 0

となります。

以下が、その、コードです。

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

Private Sub btnIko_Click(以下、略)
Dim cn As New SqlClient.SqlConnection(接続文字列)
Dim n As Integer
Dim i As Integer

Dim strSQL As String
Dim strValue As String
Dim strIns As String
Dim strUpd As String

Dim da As SqlClient.SqlDataAdapter
Dim ds As DataSet
Dim dt As DataTable
Dim dr() As DataRow

Dim cmdIns As SqlClient.SqlCommand
Dim cmdUpd As SqlClient.SqlCommand

Try
cn.Open()
strSQL = "select * from [T_FROM] order by [FROMID]"
da = New SqlClient.SqlDataAdapter(strSQL, cn)
ds = New DataSet
da.Fill(ds, "T_FROM")
dt = ds.Tables("T_FROM")
dr = dt.Select

n = 0
i = 0
For i = 0 To dr.Length - 1
If n = 0 Then
strValue = ""
strValue &= "0,0,0"
strIns = "insert into [T_TO]([数値1],[数値2],[数値3]) values (" & strValue & ")"
cmdIns = New SqlClient.SqlCommand(strIns, cn)
cmdIns.ExecuteNonQuery()

End If
strUpd = ""
Select Case n
Case 0
strUpd &= "update [T_TO] set [数値1] = " & CInt(dr(i)("数値")) & ""
Case 1
strUpd &= "update [T_TO] set [数値2] = " & CInt(dr(i)("数値")) & ""
Case 2
strUpd &= "update [T_TO] set [数値3] = " & CInt(dr(i)("数値")) & ""
End Select

cmdUpd = New SqlClient.SqlCommand(strUpd, cn)
cmdUpd.ExecuteNonQuery()

If n = 2 Then
n = 0
Else
n = n + 1
End If
Next

dr = Nothing
da = Nothing
dt = Nothing
dr = Nothing

MsgBox("変換完了しました。")

Catch ex As Exception
MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error)
Finally

End Try
End Sub

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

上記のコードを実行すると、


T_FROM
数値1 数値2 数値3
4 5 3
4 5 0

という結果に、なってしまいます。
上記のUPDATE文(strUpd)で、UPDATEを実行する直前にINSERTした行、を、指定することが出来ていないため、
すべての行に対して、UPDATEが実行されてしまっています。
この、INSERTした行を、UPDATE文中で、いかに指定したらよいか、悩んでおります。

これが、MicrosoftAccessのSELECT文の場合は、T_TOの[TOID]を昇順に並べておき、SELECT LAST 1 文を使うか、
または、降順に並べておき、SELECT TOP 1 文を使うか、の、方法があると思いますが、
この、メソッドも、調べますと、ORDER BYは考慮せず、テーブルに格納された順番に従うため、期待通りの結果を取得しない場合がある、と、ありました。
SQLServerでは、使用出来ない、書き方です。

また、T_TOに、新たなフラグフィールドを追加して、
INSERT実行前に、一度、すべてクリアして、
INSERTした際に、その行にのみ、フラグを立てる、という方法も、
考えられますが、
T_TOに、フィールドを増やすことが出来ない、という、現状が、ございます。

お分かりになられる方がいらっしゃいましたら、ご教示くださいませ。
どうぞ、よろしくお願い申し上げます。
こんばんは。

(DataSet使わないのにDataTableではなく一旦DataSetにFillして受け取る意味も分かりませんし、
色々どうかと思う点がありますが…)

同じメソッド内で直後に加工するのが前提なのになんで一旦正しくない形(0,0,0)でinsertするんですか?

for文で刻みを「step 3」にして、元データ側のレコード数を3で割った商(切り捨て整数)の回数だけ
{カウント回・カウント回+1・カウント回+2}分をまとめた1文でinsert実行した後に、
ループの外で、余りの分のを組み立てたinsert文を1回(※余りゼロなら0回、1か2なら1回。)実行するだけでよいのでは。
■No31530に返信(とん。さんの記事)

ありがとうございます。
実は、実際には、さらに複雑な、プログラムを、組んでおりまして、
その、一部を、質問用に、加工したものでして。


> (DataSet使わないのにDataTableではなく一旦DataSetにFillして受け取る意味も分かりませんし、
> 色々どうかと思う点がありますが…)

失礼しました。
DataTableを使う際に、まず、Datasetに受け取る、という方法を、とってきました。DatasetをUpdateすることも、ありまして。

>
> 同じメソッド内で直後に加工するのが前提なのになんで一旦正しくない形(0,0,0)でinsertするんですか?

取り組んでいるプログラムで、値がない数値の部分には、0を入れる、がありまして(実際には、テキスト型のフィールドが、たくさんあります)。最初に、数値をあてはめ、あとで、Nullの部分に、0を入れる、より、先に、初期値0を入れて、数値がある部分だけ、更新する、ように、しております。

>
> for文で刻みを「step 3」にして、元データ側のレコード数を3で割った商(切り捨て整数)の回数だけ
> {カウント回・カウント回+1・カウント回+2}分をまとめた1文でinsert実行した後に、
> ループの外で、余りの分のを組み立てたinsert文を1回(※余りゼロなら0回、1か2なら1回。)実行するだけでよいのでは。

ありがとうございます。えn
検討してみます。
■No31531に返信(ERIさんの記事)

UPDATEの対象を絞り込む方法としてはINSERTのときに主キーを取得してUPDATEの
WHERE句で指定するというのも考えられます。主キーはオートナンバーとのことなの
で、SELECT SCOPE_IDENTITY()で取得できるのでないかと思います。

こんな感じです。
strIns = "insert into [T_TO]([数値1],[数値2],[数値3]) values (" & strValue & "); select scope_identity()"
cmdIns = New SqlClient.SqlCommand(strIns, cn)
toid = cmdIns.ExecuteScalar()
・・・
update [T_TO] set [数値1] = " & CInt(dr(i)("数値")) & " where TOID = " & toid
■No31534に返信(もりおさんの記事)

もりお様、ありがとうございます。
こちらの方法で、やってみます。

> ■No31531に返信(ERIさんの記事)
>
> UPDATEの対象を絞り込む方法としてはINSERTのときに主キーを取得してUPDATEの
> WHERE句で指定するというのも考えられます。主キーはオートナンバーとのことなの
> で、SELECT SCOPE_IDENTITY()で取得できるのでないかと思います。
>
> こんな感じです。
> strIns = "insert into [T_TO]([数値1],[数値2],[数値3]) values (" & strValue & "); select scope_identity()"
> cmdIns = New SqlClient.SqlCommand(strIns, cn)
> toid = cmdIns.ExecuteScalar()
> ・・・
> update [T_TO] set [数値1] = " & CInt(dr(i)("数値")) & " where TOID = " & toid
皆様に教えていただきました方法で、解決いたしました。
誠に、ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板