C#如何把百万级的excel数据导入到sqlserver数据库中去
作者:互联网
想来大家都有这样的生活常识,一个正常人一顿能吃三个拳头大小的馒头,但是你让他一次性吃三百个馒头,那他撑不死我就表演胸口碎大石…
好了,我们言归正传,在我们处理一个有好几十万条数据的excel表格时,我们的电脑一般都会卡死,甚至会死机。这就是因为我们的数据量太大了,导致我们的计算机内存不足或者溢出(你的电脑只能吃三个馒头,你非让他吃三百个,它能受到了吗?)。所以我们一般的做法是把百万级的数据导入到数据库中去,然后用数据库做处理。可是现在问题来了,我们如何把几百万条数据直接导入到数据库里面去?
常规的Excel数据导入数据库的方法,博主这里就不赘述了,但是常规的方法都有一个绕不过去的坎,就是内存溢出的问题,因为无论前面的步骤如何不同,到最后都是要一次性读取数据,然后就是程序崩溃,电脑卡死的结果。这里我为大家提供一个新的思路,可以用来将百万级的excel数据导入到sqlserver数据库中去。这个思路的核心思想就是分批导入数据+SqlBulkCopy工具。
我们的电脑毕竟不是真正的人,它虽然一次性无法吃掉三百个馒头,但是它的“消化功能”非常的好,它吃完三个馒头后就可以立马在吃三个馒头,就这样,我一次吃三个,我吃一百次,我三百个馒头也就吃完了。同样,我一次只导入一万条数据,我一百次就能导入一百万条数据!好了原理就阐述到这里,接下来我们看一下代码部分:
public void TransferData(string excelFile, string sheetName, string connectionString)
{
// try
{
string strConn = "";
//获取全部数据
FileInfo file = new FileInfo(excelFile);
if (!file.Exists) { throw new Exception("文件不存在"); }
string extension = file.Extension;
if (extension == ".xls")
strConn = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 8.0;HDR=Yes;IMEX=1;'", excelFile);
if (extension == ".xlsx")
strConn = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 12.0;HDR=Yes;IMEX=1;'", excelFile);
if (strConn == "") { throw new Exception("excel版本过低,请更换成Office2007以上版本"); }
OleDbConnection conn = new OleDbConnection(strConn);
conn.Open();
string strExcel = "";
int stat = 0;
int end = 10000;
//分批次导入数据
for (int i = 0; i < 100; i++)// 如果数据量超过一百万,for循环里面的循环次数可以调整一下,当然你可以改一下,获取excel总条数,然后自动的控制循环次数
{
strExcel = string.Format(@" select * from [Sheet1$]
where id >={0} and id <{1}", stat, end);//这里其实也不完美,这里可以看到博主需要在表列添加一列序号列,用以分割数据,如果有哪位大神可以指点一下,access语法怎么添加一列序号列,小弟不胜感激。(access的语法和sqlserver还是有一些差异的)
//注意一下excel的sheet名称必须是Sheet1,有人觉得麻烦可以自己改一下代码将表名根据excel实际情况动态获取。
stat = stat + 10000;
end = end + 10000;
OleDbDataAdapter myCommand = new OleDbDataAdapter(strExcel, strConn);
DataSet ds = new DataSet();
myCommand.Fill(ds, sheetName);
//如果目标表不存在则创建
string strSql = string.Format("if object_id('{0}') is null create table {0}(", sheetName);
foreach (System.Data.DataColumn c in ds.Tables[0].Columns)
{
strSql += string.Format("[{0}] varchar(1000),", c.ColumnName);
}
strSql = strSql.Trim(',') + ")";
using (System.Data.SqlClient.SqlConnection sqlconn = new System.Data.SqlClient.SqlConnection(connectionString))
{
sqlconn.Open();
System.Data.SqlClient.SqlCommand command = sqlconn.CreateCommand();
command.CommandText = strSql;
command.ExecuteNonQuery();
sqlconn.Close();
}
//用bcp导入数据
using (System.Data.SqlClient.SqlBulkCopy bcp = new System.Data.SqlClient.SqlBulkCopy(connectionString))
{
bcp.SqlRowsCopied += new System.Data.SqlClient.SqlRowsCopiedEventHandler(bcp_SqlRowsCopied);
bcp.BatchSize = 100;//每次传输的行数
bcp.NotifyAfter = 100;//进度提示的行数
bcp.DestinationTableName = sheetName;//目标表
bcp.WriteToServer(ds.Tables[0]);
}
}
MessageBox.Show("导入成功");
}
// catch (Exception ex)
{
// System.Windows.Forms.MessageBox.Show(ex.Message);
}
}
//进度显示
void bcp_SqlRowsCopied(object sender, System.Data.SqlClient.SqlRowsCopiedEventArgs e)
{
this.Text = e.RowsCopied.ToString();
this.Update();
}
代码大家可以拿去直接用,博主测试了一下40万条数据插入数据库用时三分钟左右。博主逛博客多年,遇到问题总是能在博客找到思路或者答案,在这里首先对这些前辈表示感谢!前人栽树后人乘凉,希望有更多的人能将自己遇到的问题和解决方案共享出来,大家共同进步。赠人玫瑰,手有余香,也祝各位在2020年白白胖胖,充满希望~
标签:导入到,馒头,string,C#,excel,数据库,sqlserver,strConn,数据 来源: https://blog.csdn.net/hexin0078/article/details/106850833