怎么样快速向SQL数据库插入大数据量的数据

怎么样快速向SQL数据库插入大数据量的数据,第1张

添加数据需要知道往哪张表添加,以及自己要添加的内容,然后可用insert语句执行。

1、以sqlserver2008r2为例,登录SQL Server Management Studio到指定的数据库。

2、登录后点击“新建查询”。

3、比如要往test表中插入数据,可先用如下语句查看一下表结构及表内数据:

1select * from test

4、根据自己的实际情况添加输入,比如要添加一条“16,du小小动”的数据。

1insert into test (id,name) values (16,'du小小动')

执行成功后会有提示:

5、此时数据库中数据如下,说明添加成功。

一、SqlServer数据批量插入

SqlServer的批量插入很简单,使用SqlBulkCopy就可以,以下是该类的实现:

复制代码

/// <summary>

/// 为 System.Data.SqlClient 提供的用于批量操作的方法。

/// </summary>

public sealed class MsSqlBatcher : IBatcherProvider

{

/// <summary>

/// 获取或设置提供者服务的上下文。

/// </summary>

public ServiceContext ServiceContext { getset}

/// <summary>

/// 将 <see cref="DataTable"/>的数据批量插入到数据库中。

/// </summary>

/// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>

/// <param name="batchSize">每批次写入的数据量。</param>

public void Insert(DataTable dataTable, int batchSize = 10000)

{

Checker.ArgumentNull(dataTable, "dataTable")

if (dataTable.Rows.Count == 0)

{

return

}

using (var connection = (SqlConnection)ServiceContext.Database.CreateConnection())

{

try

{

connection.TryOpen()

//给表名加上前后导符

var tableName = DbUtility.FormatByQuote(ServiceContext.Database.Provider.GetService<ISyntaxProvider>(), dataTable.TableName)

using (var bulk = new SqlBulkCopy(connection, SqlBulkCopyOptions.KeepIdentity, null)

{

DestinationTableName = tableName,

BatchSize = batchSize

})

{

//循环所有列,为bulk添加映射

dataTable.EachColumn(c =>bulk.ColumnMappings.Add(c.ColumnName, c.ColumnName), c =>!c.AutoIncrement)

bulk.WriteToServer(dataTable)

bulk.Close()

}

}

catch (Exception exp)

{

throw new BatcherException(exp)

}

finally

{

connection.TryClose()

}

}

}

}

SqlBulkCopy的ColumnMappings中列的名称受大小写敏感限制,因此在构造DataTable的时候应请注意列名要与表一致。

以上没有使用事务,使用事务在性能上会有一定的影响,如果要使用事务,可以设置SqlBulkCopyOptions.UseInternalTransaction。

复制代码

二、Oracle数据批量插入

System.Data.OracleClient不支持批量插入,因此只能使用Oracle.DataAccess组件来作为提供者。

View Code

以上最重要的一步,就是将DataTable转为数组的数组表示,即object[][],前数组的上标是列的个数,后数组是行的个数,因此循环Columns将后数组作为Parameter的值,也就是说,参数的值是一个数组。而insert语句与一般的插入语句没有什么不一样。

三、SQLite数据批量插入

SQLite的批量插入只需开启事务就可以了,这个具体的原理不得而知。

View Code

四、MySql数据批量插入

复制代码

/// <summary>

/// 为 MySql.Data 组件提供的用于批量操作的方法。

/// </summary>

public sealed class MySqlBatcher : IBatcherProvider

{

/// <summary>

/// 获取或设置提供者服务的上下文。

/// </summary>

public ServiceContext ServiceContext { getset}

/// <summary>

/// 将 <see cref="DataTable"/>的数据批量插入到数据库中。

/// </summary>

/// <param name="dataTable">要批量插入的 <see cref="DataTable"/>。</param>

/// <param name="batchSize">每批次写入的数据量。</param>

public void Insert(DataTable dataTable, int batchSize = 10000)

{

Checker.ArgumentNull(dataTable, "dataTable")

if (dataTable.Rows.Count == 0)

{

return

}

using (var connection = ServiceContext.Database.CreateConnection())

{

try

{

connection.TryOpen()

using (var command = ServiceContext.Database.Provider.DbProviderFactory.CreateCommand())

{

if (command == null)

{

throw new BatcherException(new ArgumentException("command"))

}

command.Connection = connection

command.CommandText = GenerateInserSql(ServiceContext.Database, command, dataTable)

if (command.CommandText == string.Empty)

{

return

}

command.ExecuteNonQuery()

}

}

catch (Exception exp)

{

throw new BatcherException(exp)

}

finally

{

connection.TryClose()

}

}

}

/// <summary>

/// 生成插入数据的sql语句。

/// </summary>

/// <param name="database"></param>

/// <param name="command"></param>

/// <param name="table"></param>

/// <returns></returns>

private string GenerateInserSql(IDatabase database, DbCommand command, DataTable table)

{

var names = new StringBuilder()

var values = new StringBuilder()

var types = new List<DbType>()

var count = table.Columns.Count

var syntax = database.Provider.GetService<ISyntaxProvider>()

table.EachColumn(c =>

{

if (names.Length >0)

{

names.Append(",")

}

names.AppendFormat("{0}", DbUtility.FormatByQuote(syntax, c.ColumnName))

types.Add(c.DataType.GetDbType())

})

var i = 0

foreach (DataRow row in table.Rows)

{

if (i >0)

{

values.Append(",")

}

values.Append("(")

for (var j = 0j <countj++)

{

if (j >0)

{

values.Append(", ")

}

var isStrType = IsStringType(types[j])

var parameter = CreateParameter(database.Provider, isStrType, types[j], row[j], syntax.ParameterPrefix, i, j)

if (parameter != null)

{

values.Append(parameter.ParameterName)

command.Parameters.Add(parameter)

}

else if (isStrType)

{

values.AppendFormat("'{0}'", row[j])

}

else

{

values.Append(row[j])

}

}

values.Append(")")

i++

}

return string.Format("INSERT INTO {0}({1}) VALUES {2}", DbUtility.FormatByQuote(syntax, table.TableName), names, values)

}

/// <summary>

/// 判断是否为字符串类别。

/// </summary>

/// <param name="dbType"></param>

/// <returns></returns>

private bool IsStringType(DbType dbType)

{

return dbType == DbType.AnsiString || dbType == DbType.AnsiStringFixedLength || dbType == DbType.String || dbType == DbType.StringFixedLength

}

/// <summary>

/// 创建参数。

/// </summary>

/// <param name="provider"></param>

/// <param name="isStrType"></param>

/// <param name="dbType"></param>

/// <param name="value"></param>

/// <param name="parPrefix"></param>

/// <param name="row"></param>

/// <param name="col"></param>

/// <returns></returns>

private DbParameter CreateParameter(IProvider provider, bool isStrType, DbType dbType, object value, char parPrefix, int row, int col)

{

//如果生成全部的参数,则速度会很慢,因此,只有数据类型为字符串(包含'号)和日期型时才添加参数

if ((isStrType &&value.ToString().IndexOf('\'') != -1) || dbType == DbType.DateTime)

{

var name = string.Format("{0}p_{1}_{2}", parPrefix, row, col)

var parameter = provider.DbProviderFactory.CreateParameter()

parameter.ParameterName = name

parameter.Direction = ParameterDirection.Input

parameter.DbType = dbType

parameter.Value = value

return parameter

}

return null

}

}


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/54684.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-02-26
下一篇2023-02-26

发表评论

登录后才能评论

评论列表(0条)

    保存