質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

3回答

4696閲覧

DataTableをSQLServerにInsertする

pon108

総合スコア19

VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2019/07/26 02:59

前提・実現したいこと

Visual Studio2019を使用して 在庫管理Windowsアプリケーションを作成しております。 その中でExcelファイルを読み込み、Formに配置しているDataGridViewに表示を行い 表示された内容をSQLServerに用意している2つのTABLEにInsertするようにしたいと考えております。 登録部分で躓いてしまったため書けておりませんが登録するデータの重複チェックを行い、 重複していない時は両TableにINSERT、 重複しているようであれば  ・mst_tableにはINSERTしない  ・DATA_tableは重複しているデータの数量の部分に足す(UPDATE) 行うようにしたいと考えております。 ■Formに配置されているコントロール  ・Button1 ⇒ OpenFileDialogを使用してExcelファイルを選択してDataGridView1に表示  ・Button2 ⇒ DataGridView1に表示されている内容をSQLServerにInsert  ・DataGridView1 ⇒ 読み込んだExcelファイルの表示 読み込むExcelファイルは8列×3000行ぐらいです。 列数は固定で、行数は可変となります。 ■INSERTするTable(データ型)  ・mst_table ⇒ 品物マスター    ・列名1 … nvarchar(50)    ・列名2 … nvarchar(50)    ・列名3 … nvarchar(50)    ・列名4 … decimal(8, 0)    ・列名5 … varbinary(MAX)    ・列名6 … nvarchar(50)    ・列名7 … date    ・列名8 … nvarchar(50)  ・DATA_table ⇒ 品物の在庫数量管理    ・列名1 … nvarchar(50)    ・列名2 … int    ・列名3 … datetime

発生している問題・エラーメッセージ

DataGridViewに表示した内容をDBへ登録する際に下記エラーが発生します。 ・エラーメッセージ  「実行タイムアウトの期限が切れました。操作完了前にタイムアウト期間が過ぎたか、サーバーが応答していません。」 DataTableの内容を順番に確認をしながらInsertしているので発生しているのだと思うのですが 今の私ではこれ以外に良い方法が見つかりませんでした。

該当のソースコード

VB

1 Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click 2 3 Dim dt As New DataTable 4 5 dt = DataGridView1.DataSource 6 7 Call insert_Table(dt) 8 9 End Sub 10 11 Sub insert_Table(ByVal dt As DataTable) 12 13 Dim check_Sql As String = Nothing 14 Dim Insert_Sql_mst As String = Nothing 15 Dim Insert_Sql_DATA As String = Nothing 16 Dim sinamono As String = Nothing 17 Dim used As Boolean = True 18 19 20 Using db_cn As New SqlConnection(接続文字列) 21 Using db_cmd As SqlCommand = db_cn.CreateCommand 22 23 db_cn.Open() 24 25 Try 26 27 db_cmd.Transaction = db_cn.BeginTransaction() 28 29 For i As Integer = 0 To dt.Rows.Count - 1 30 31 sinamono = dt.Rows(i)("EXCEL列名2").ToString 32 33 If sinamono <> Nothing Then 34 35 mySql_check = "SELECT COUNT(*) " 36 mySql_check &= "FROM mst_table " 37 mySql_check &= "WHERE EXCEL列名2 = '" & sinamono & "'" 38 39 40 '******【すでに登録されているか確認】********* 41 42 ml_function.UsedCode(check_Sql) 43 44 '***************************************** 45 46 47 '登録がなかった場合、【新規登録(INSERT)】 48 If used = True Then 49 50 Insert_Sql_mst = "INSERT INTO mst_table " 51 Insert_Sql_mst &= "(列名1, 列名2, 列名3, 列名4, 列名5, 列名6, 列名7, 列名8)" 52 Insert_Sql_mst &= "VALUES(" 53 Insert_Sql_mst &= "'" & dt.Rows(i)("EXCEL列名1").ToString & "', " 54 Insert_Sql_mst &= "'" & dt.Rows(i)("EXCEL列名2").ToString & "', " 55 Insert_Sql_mst &= "'" & dt.Rows(i)("EXCEL列名3").ToString & "', " 56 Insert_Sql_mst &= "'" & CInt(dt.Rows(i)("EXCEL列名4").ToString) & "', " 57 Insert_Sql_mst &= "NULL, " 58 Insert_Sql_mst &= "'" & dt.Rows(i)("EXCEL列名6").ToString & "', " 59 Insert_Sql_mst &= "'" & DateTime.Now() & "', " 60 Insert_Sql_mst &= "'" & My.Settings.変数 & "'" 61 Insert_Sql_mst &= ")" 62 63 Insert_Sql_DATA = "INSERT INTO DATA_table " 64 Insert_Sql_DATA &= "(列名1, 列名2, 列名3) " 65 Insert_Sql_DATA &= "VALUES(" 66 Insert_Sql_DATA &= "'" & dt.Rows(i)("EXCEL列名2").ToString & "', " 67 Insert_Sql_DATA &= "'" & CInt(dt.Rows(i)("EXCEL列名7").ToString) & "', " 68 Insert_Sql_DATA &= "'" & DateTime.Now() & "'" 69 Insert_Sql_DATA &= ")" 70 71 72 db_cmd.CommandText = Insert_Sql_mst 73 db_cmd.ExecuteNonQuery() 74 75 db_cmd.CommandText = Insert_Sql_DATA 76 db_cmd.ExecuteNonQuery() 77 78 End If 79 80 End If 81 82 Next 83 84 db_cmd.Transaction.Commit() 85 86 MessageBox.Show("登録完了。") 87 88 Catch ex As Exception 89 90 MessageBox.Show(ex.Message, "エラー") 91 db_cmd.Transaction.Rollback() 92 93 End Try 94 95 End Using 96 End Using 97 End Sub 98 99 Public Function UsedCode(check_Sql As String) As Boolean 100 101 '※存在している時はTrue 102 Dim used As Boolean = True 103 104 105 Using db_con As New SqlConnection(接続文字列) 106 107 Using db_cmd As SqlCommand = db_con.CreateCommand() 108 109 db_con.Open() 110 111 Dim db_dr As SqlDataReader 112 113 db_cmd.CommandText = check_Sql 114 115 db_dr = db_cmd.ExecuteReader() 116 117 If db_dr.HasRows Then 118 db_dr.Read() 119 If db_dr(0) = 0 Then 120 'カウント0で存在なしはFalse 121 used = False 122 123 End If 124 End If 125 126 End Using 127 End Using 128 129 Return used 130 131 End Function

試したこと

下記サイトを参考にDataTableを一括登録する方法など考えましたがDataGridViewに表示した内容を
二つのDataTableに分けて登録するような応用が出来ませんでした。

参考サイト
リンク

補足情報(FW/ツールのバージョンなど)

Visual Studio2019
SQLServer2016
開発言語 VB

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

DataTableをSQLServerにInsertする

登録するデータの重複チェックを行い云々のあたりが理解できていませんが、もし、最終的な INSERT 用の DataTable が完成できているのであれば、以下の記事に書いてあるような手段は使えないでしょうか?

DataAdapter を使用したバッチ操作の実行
https://docs.microsoft.com/ja-jp/dotnet/framework/data/adonet/performing-batch-operations-using-dataadapters

投稿2019/07/26 07:43

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pon108

2019/07/27 02:23

回答ありがとうございます。 教えていただきましたサイトを確認しました。 ただ読み解くのに少し時間が掛かりそうなので参考にさせていただき、勉強してみます。
guest

0

ベストアンサー

追加処理のトランザクションと存在有無のチェック内のSELECTコマンドが別トランザクションとなっているために、ロックがかかっているのではないでしょうか?

VBNET

1 Public Function UsedCode(con As SqlConnection, trn As SqlTransaction, check_Sql As String) As Boolean 2 3 '※存在している時はTrue 4 Dim used As Boolean = True 5 6 Using db_cmd As SqlCommand = con.CreateCommand() 7 8 db_cmd.Transaction = trn 9 db_cmd.CommandText = check_Sql 10 11 Dim db_dr As SqlDataReader = db_cmd.ExecuteReader() 12 13 If db_dr.HasRows Then 14 db_dr.Read() 15 If db_dr(0) = 0 Then 16 'カウント0で存在なしはFalse 17 used = False 18 19 End If 20 End If 21 22 End Using 23 24 Return used 25 26 End Function 27

といった感じで、同じコネクション、同じトランザクションを使用するようにしてはどうでしょうか?

追記
リンク先の方法ですと、ストアドを作成しての3番の方法がいいのではないでしょうか?
そのストアドの中で存在チェック等を行い、INSERT、UPDATEを実行すればいいでしょう。

投稿2019/07/26 04:15

編集2019/07/26 04:46
YAmaGNZ

総合スコア10258

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pon108

2019/07/27 02:21

回答ありがとうございます。 教えていただいたように同じコネクション、トランザクションを使用するように変更してみたのですが 今度は「この Command に関連付けられている DataReader が既に開かれています。このコマンドを最初に閉じる必要があります。」とエラーが出ます。 調べたところ、「DataReaderはひとつの接続に対して1つしか開くことができません。」とあったのですが、DataReader は一度しか使っていないと思っているのですが… 何か他に原因があるのでしょうか?
YAmaGNZ

2019/07/27 03:16

SqlDataReaderは使い終わったらCloseしてください。 また、Countを取るだけであれば、ExecuteReaderを使用するのではなくExecuteScalarを使用したほうがよろしいかと
pon108

2019/07/27 16:40

ありがとうございます。本当に助かりました。 教えていただきました内容で無事に解決することが出来ました。 またアドバイスいただきましたようにExecuteScalarを使用するように変更しました。
guest

0

DataTableを一括登録する方法など考えましたがDataGridViewに表示した内容を
二つのDataTableに分けて登録するような応用が出来ませんでした。

リンク先のサンプルだとFROMは同じで出力するテーブルやselect項目を変更した、SQLをそれぞれ発行するようにすれば良いのでは。

ところで、データをマスタとトランザクションに分けて追加する場合、外部参照の状態でしょうから、マスターに追加する部分は重複を避けたり、登録済みの除外とか不要でないのかが気になります。

投稿2019/07/26 04:12

sazi

総合スコア25195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pon108

2019/07/27 16:44

回答ありがとうございました。 参考にしているサイトの内容をもう一度読み直し、別の書き方も学んでみます。 また追加のアドバイスをいただき、ありがとうございます。 確かに必要な部分なので追加してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問