使用 SqlBulkCopy 读取 .CSV 文件并将数据插入到 SQL 表






3.70/5 (7投票s)
在本文中,我们将讨论如何使用 sqlbulkcopy。

引言
对于程序员/用户来说,常见的情况是需要将来自不同数据源的数据插入到 sqlserver 数据库表中。使用 sqlserver 集成的导入数据功能很容易做到。但是,如果您使用的是 sqlexpress,它是一个轻量级版本,不支持数据导入,该怎么办?
而且,数据导入功能有时可能无法满足业务需求。您可能不希望用户直接访问数据库。
如果您有一个包含 10000000 行的文件,并且在读取每一行后需要进行一些验证,并需要使用特定的编程逻辑进行解析,该怎么办?直接数据导入在那个时候将不起作用。
最好在代码中实现您的业务逻辑,而不是在数据库中使用存储过程、视图和函数。编写一个包含 3000 行的存储过程不是一个好主意。当调试这种存储过程时,您肯定会遇到麻烦。Insert
、Delete
、Update
和 Select
语句最适合在没有验证的情况下在数据库中执行。
解决此问题
有很多方法可以解决这类问题。但最常见的方法是
- 您可以使用 SQL 命令
- 您可以使用
SQLBulkCopy
(比 sqlcommand 更快,但不会触发数据库触发器)
在本文中,我们将讨论如何使用 sqlbulkcopy。
以下是分步解决方案
- 首先,我们将使用以下代码创建 sqltable。您需要在数据库查询窗口中执行此操作
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Company]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) drop table [dbo].[Company] GO CREATE TABLE [dbo].[Company] ( [CompanyName] [varchar] (500) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL , [Volume] [varchar] (500) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ) ON [PRIMARY] GO
- 其次,我们将创建一个项目。并将以下控件放置在默认的
Form1
窗体中,并同时放置代码。- 1 个文本框用于指定服务器配置。
- 1 个文本框用于指定要读取的文件的文件路径。
- 1 个文本框用于指定数据存储的位置。
- 1 个打开文件对话框以打开指定的文件。
- 一个按钮,命名为
btnLoadFile
以加载文件路径private void btnLoadFile_Click(object sender, EventArgs e) { try { //I have used a open file Dialog to let the //program know where the file is located DialogResult dResult = new DialogResult(); //Dialog result sets the openfile dialog result dResult = openFileDialog1.ShowDialog(); if (dResult == DialogResult.OK) //If dialog result is ok, then show the file //name and path in the Text box { txtFilePath.Text = openFileDialog1.FileName; } else { return; //If Dialog result is other than ok, then do nothing } } catch (Exception exp) { MessageBox.Show(exp.Message);//Catch any exception if occurs } }
- 一个
DataGridView
控件以显示数据 - 一个按钮,命名为
btnLoadData
以将数据从文件加载到gridview
private void btnLoadData_Click(object sender, EventArgs e) { try { if (string.IsNullOrEmpty(txtFilePath.Text.Trim())) //Check if //file was supplied { MessageBox.Show("Please supply file name"); return; } System.IO.StreamReader rdr = new System.IO.StreamReader(txtFilePath.Text.Trim()); //Stream reader reads a file. File path //and name are supplied from where to read the file. string inputLine = ""; DataTable dt = new DataTable(); //A data table is similar to a Database table. //Define the columns. dt.Columns.Add("CompanyName"); dt.Columns.Add("Volume"); DataRow row; //Declare a row, which will be added to the above data table while ((inputLine = rdr.ReadLine()) != null) //Read while the line is not null { string[] arr; arr = inputLine.Split(','); //splitting the line which was read by the stream reader object row = dt.NewRow(); row["Companyname"] = arr[0]; row["Volume"] = arr[1]; dt.Rows.Add(row); } dt.Rows.RemoveAt(0); //Remove the first column since its //the column name not necessary to insert in the database table dataGridView1.DataSource = dt; //setting the data source to the gridview rdr.Close(); //release the stream reader } catch (Exception) { throw; } }
- 一个按钮,命名为
btnSaveFile
以将原始数据保存到数据库。private void btnSaveFile_Click(object sender, EventArgs e) { try { if (string.IsNullOrEmpty(txtServerConfiguration.Text.Trim())) //Check if server exists { MessageBox.Show("Please supply Server Configuration"); return; } if (string.IsNullOrEmpty(txtTableName.Text.Trim())) //Check if Table name was provided { MessageBox.Show("Please supply Table Name"); return; } SqlBulkCopy sqlbulkCopy = new SqlBulkCopy(txtServerConfiguration.Text.Trim()); //Define the Server Configuration sqlbulkCopy.DestinationTableName = txtTableName.Text.Trim(); //You need to define the target table name where //the data will be copied //Since the requirement is not to read data directly from the file //I have included a gridview, where the //raw data will be shown to the user. //So that the user can change the data if he wants for (int i = 0; i < dataGridView1.ColumnCount; i++) //reading the column names { sqlbulkCopy.ColumnMappings.Add( dataGridView1.Columns[i].Name, dataGridView1.Columns[i].Name); //Column mapping , supplying source column //and destination column } DataTable dt = new DataTable(); dt = (DataTable)dataGridView1.DataSource; //Storing the data in a data table, though you can do it by //directly passing Grid View Data Source to the following function sqlbulkCopy.WriteToServer(dt); sqlbulkCopy.Close();//Release the resources MessageBox.Show("Saved Successfully"); } catch (Exception exp) { MessageBox.Show(exp.Message);//Catch any exception if occurs } }
关注点
我无法在任何地方找到像这样的完整解决方案。我学习了如何使用 SQL bulk copy 将文件读取并写入数据库表。由于生活中会发生错误,任何评论/信息/激烈的反应都将受到欢迎。
历史
- 2010 年 2 月 11 日:初始发布
我会不时更新这篇文章。