@AdaTheDevの回答は正しいです。しかし、これを行うための別の方法があります。
一括インポート中に重複挿入の問題がある場合は、一括コピー機能を使用する代わりにストアドプロシージャを使用して処理することもできます。
2005年以降のバージョンのSQL Serverでは、 "テーブル値のパラメータ"を使用できます。つまり、テーブル全体をパラメータとしてストアドプロシージャに渡してサーバー側で操作できます。
「マージコマンド」よりもストアドプロシージャパラメータを使用してサーバー側にテーブルを渡す場合、mergeコマンドはupsertコマンドです。つまり、同じコマンドから必要なレコードを挿入したり更新したり削除したりすることができます。ここで
は、プロセスに関するいくつかの詳細は以下のとおりです。
ステップ1: SQL Serverでテーブル値パラメータとして作成します。コマンドは次のとおりです。ここで
CREATE TYPE [dbo].[TableTypeName] AS TABLE(
[ColumnName1] [DataType],
[ColumnName2] [DataType],
[ColumnName3] [DataType]
)
GO
「ColumnName1,2,3」表の列の名前とは「データ型」は、列に割り当てられたSQL Serverのデータ型です。
ステップ2:
CREATE PROCEDURE [dbo].[ProcedureName]
@TableTypeName [dbo].[TableTypeName] READONLY
AS
BEGIN
DECLARE @InsertedRowsId TABLE
(
[InsertedRowId] [DataType] NOT NULL
);
DELETE FROM @InsertedRowsId;
BEGIN TRY
BEGIN TRANSACTION
-- Merge command
MERGE INTO [dbo].[TableName] AS [Target]
USING (
SELECT * FROM @TableTypeName
) AS [Source]
-- Candidate Keys: All the column(s) combination that makes the record(s) unique.
ON [Target].[ColumnName1] = [Source].[ColumnName1] -- Always false, ensures all rows copied
AND [Target].[ColumnName2] = [Source].[ColumnName2]
AND [Target].[ColumnName2] = [Source].[ColumnName2]
WHEN NOT MATCHED THEN
INSERT
(
[ColumnName1]
,[ColumnName1]
,[ColumnName1]
)
VALUES
(
[Source].[ColumnName1]
,[Source].[ColumnName1]
,[Source].[ColumnName1]
);
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
END CATCH
END
ステップ3:ストアドプロシージャを呼び出す今最終段階をようmergeコマンドでストアドプロシージャを作成します。
Private void button1_Click(object sender, EventArgs e)
{
string connectionString = @"server=localhost;Initial Catalog=klantbestand;Integrated Security=SSPI;";
string filepath = @"C:\clients TEST.csv";
StreamReader sr = new StreamReader(filepath);
string line = sr.ReadLine();
string[] value = line.Split(';');
DataTable dt = new DataTable();
DataRow row;
foreach (string dc in value)
{
dt.Columns.Add(new DataColumn(dc));
}
while (!sr.EndOfStream)
{
value = sr.ReadLine().Split(';');
if (value.Length == dt.Columns.Count)
{
row = dt.NewRow();
row.ItemArray = value;
dt.Rows.Add(row);
}
}
if (dt.Rows.Count>0) {
using (SqlConnection connection = new SqlConnection(connectionString)) {
connection.Open();
using (SqlCommand command = connection.CreateCommand()) {
command.CommandText = "dbo.ProcedureName";
command.CommandType = CommandType.StoredProcedure;
SqlParameter parameter;
parameter = command.Parameters.AddWithValue("@TableTypeName", dt);
parameter.SqlDbType = SqlDbType.Structured;
parameter.TypeName = "dbo.TableTypeName";
command.ExecuteNonQuery();
}
}
}
}
このようにして、重複するレコードを一切持たずにデータを一括インポートすることができます。 必要に応じて、挿入または例外の詳細を記録することもできます。
何らかの種類のミューテックスを作成したり、ボタンが機能している間は無効にするのは安全な選択肢ではないでしょうか? – rualmar
ボタンを2回押すだけではありません。 csvファイルと同じ値がすでにデータベースにある場合です。 – Stijn