c#批量插入数据到sqlserver

4 篇文章 1 订阅

方法一:逐条插入,性能最差,不推荐使用

INSERT INTO Test(Id, Name) VALUES(newid(), '1');
INSERT INTO Test(Id, Name) VALUES(newid(), '2');

C#方法

static void InsertOne()
{
    Console.WriteLine("采用一条一条插入的方式实现");
    Stopwatch sw = new Stopwatch();

    using (SqlConnection conn = new SqlConnection(StrConnMsg)) //using中会自动Open和Close 连接。
    {
        string sql = "INSERT INTO Test(Id,Name) VALUES(newid(),@p)";
                conn.Open();
        for (int i = 0; i < totalRow; i++)
        {
            using (SqlCommand cmd = new SqlCommand(sql, conn))
            {
                cmd.Parameters.AddWithValue("@p", i);
                sw.Start();
                cmd.ExecuteNonQuery();
                Console.WriteLine(string.Format("插入一条记录,已耗时{0}毫秒", sw.ElapsedMilliseconds));
            }
            if (i == getRow)
            {
                sw.Stop();
                break;
            }
        }
    }
    Console.WriteLine(string.Format("插入{0}条记录,每{4}条的插入时间是{1}毫秒,预估总得插入时间是{2}毫秒,{3}分钟", totalRow, sw.ElapsedMilliseconds, ((sw.ElapsedMilliseconds / getRow) * totalRow), GetMinute((sw.ElapsedMilliseconds / getRow * totalRow)), getRow));
}

static int GetMinute(long l)
{
    return (Int32)l / 60000;
} 

结论

插入100w条记录,预计需要50分钟时间,每插入一条记录大概需要3毫秒左右。

方法二:拼接sql

INSERT INTO Test(Id, Name) VALUES(newid(), '1'),(newid(), '2')

C#方法

static void InsertFour()
{
    Console.WriteLine("采用拼接批量SQL插入的方式实现");
    Stopwatch sw = new Stopwatch();

    using (SqlConnection conn = new SqlConnection(StrConnMsg)) //using中会自动Open和Close 连接。
    {
        conn.Open();
        sw.Start();
        for (int j = 0; j < totalRow / getRow;j++ )
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("INSERT INTO Product(Id,Name,Price) VALUES");
            using (SqlCommand cmd = new SqlCommand())
            {
                       
                for (int i = 0; i < getRow; i++)
                {
                    sb.AppendFormat("(newid(),'{0}'),", i);
                }
                cmd.Connection = conn;
                cmd.CommandText = sb.ToString().TrimEnd(',');
                cmd.ExecuteNonQuery();
            }
        }
        sw.Stop();
        Console.WriteLine(string.Format("插入{0}条记录,共耗时{1}毫秒",totalRow,sw.ElapsedMilliseconds));
    }
}

结论

插入100w条记录,预计需要10分钟时间

方法三:使用Bulk

BULK INSERT    
   [ database_name . [ schema_name ] . | schema_name . ] [ table_name | view_name ] 
      FROM 'data_file'    
     [ WITH    
        (    
   [ [ , ] BATCHSIZE = batch_size ]    --BATCHSIZE指令来设置在单个事务中可以插入到表中的记录的数量   
   [ [ , ] CHECK_CONSTRAINTS ]     --指定在大容量导入操作期间,必须检查所有对目标表或视图的约束。若没有 CHECK_CONSTRAINTS 选项,则所有 CHECK 和 FOREIGN KEY 约束都将被忽略,并且在此操作之后表的约束将标记为不可信。   
   [ [ , ] CODEPAGE = { 'ACP' | 'OEM' | 'RAW' | 'code_page' } ]  --指定该数据文件中数据的代码页   
   [ [ , ] DATAFILETYPE =    
      { 'char' | 'native'| 'widechar' | 'widenative' } ]  --指定 BULK INSERT 使用指定的数据文件类型值执行导入操作。   
   [ [ , ] FIELDTERMINATOR = 'field_terminator' ]  --标识分隔内容的符号   
   [ [ , ] FIRSTROW = first_row ]    --指定要加载的第一行的行号。默认值是指定数据文件中的第一行   
   [ [ , ] FIRE_TRIGGERS ]     --是否启动触发器   
   [ [ , ] FORMATFILE = 'format_file_path' ]    
   [ [ , ] KEEPIDENTITY ]   --指定导入数据文件中的标识值用于标识列   
   [ [ , ] KEEPNULLS ]    --指定在大容量导入操作期间空列应保留一个空值,而不插入用于列的任何默认值   
   [ [ , ] KILOBYTES_PER_BATCH = kilobytes_per_batch ]    
   [ [ , ] LASTROW = last_row ]   --指定要加载的最后一行的行号   
   [ [ , ] MAXERRORS = max_errors ]   --指定允许在数据中出现的最多语法错误数,超过该数量后将取消大容量导入操作。   
   [ [ , ] ORDER ( { column [ ASC | DESC ] } [ ,...n ] ) ]  --指定数据文件中的数据如何排序   
   [ [ , ] ROWS_PER_BATCH = rows_per_batch ]    
   [ [ , ] ROWTERMINATOR = 'row_terminator' ]   --标识分隔行的符号   
   [ [ , ] TABLOCK ]     --指定为大容量导入操作持续时间获取一个表级锁   
   [ [ , ] ERRORFILE = 'file_name' ]   --指定用于收集格式有误且不能转换为 OLE DB 行集的行的文件。   
        )]

C#方法

static void InsertTwo()
{
    Console.WriteLine("使用Bulk插入的实现方式");
    Stopwatch sw = new Stopwatch();
    DataTable dt = GetTableSchema(); 

    using (SqlConnection conn = new SqlConnection(StrConnMsg))
    {
        SqlBulkCopy bulkCopy = new SqlBulkCopy(conn);
        bulkCopy.DestinationTableName = "Product";
        bulkCopy.BatchSize = dt.Rows.Count;
        conn.Open();
        sw.Start();
        
        for (int i = 0; i < totalRow;i++ )
        {
            DataRow dr = dt.NewRow();
            dr[0] = Guid.NewGuid();
            dr[1] = string.Format("商品", i);
            dr[2] = (decimal)i;
            dt.Rows.Add(dr);
        }
        if (dt != null && dt.Rows.Count != 0)
        {
            bulkCopy.WriteToServer(dt);
            sw.Stop();
        }
        Console.WriteLine(string.Format("插入{0}条记录共花费{1}毫秒,{2}分钟", totalRow, sw.ElapsedMilliseconds, GetMinute(sw.ElapsedMilliseconds)));
    }
}

static DataTable GetTableSchema()
{
    DataTable dt = new DataTable();
    dt.Columns.AddRange(new DataColumn[] {   
        new DataColumn("Id",typeof(Guid)),  
        new DataColumn("Name",typeof(string))
    });
    return dt;
}

结论

插入100w条记录,预计需要8s多

方法四:使用TVPs插入数据

创建缓存表

--Create Table Valued  
CREATE TYPE TestTemp AS TABLE  
  (Id int,  
   Name nvarchar(32))

c#方法

static void TbaleValuedToDB(DataTable dt)
{
    Stopwatch sw = new Stopwatch();
    SqlConnection sqlconn = new SqlConnection("server=.;database=TestDB;user=sa;password=123456;");
    const string TSqlStatement =
        "insert into Test (Id,Name)" +
        " SELECT tt.Id, tt.Name" +
        " FROM @TestTvp AS tt";
    SqlCommand cmd = new SqlCommand(TSqlStatement, sqlconn);
    SqlParameter catParam = cmd.Parameters.AddWithValue("@TestTvp", dt);
    catParam.SqlDbType = SqlDbType.Structured;
    catParam.TypeName = "dbo.TestTemp";
    try
    {
        sqlconn.Open();
        if (dt != null && dt.Rows.Count != 0)
        {
            cmd.ExecuteNonQuery();
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine("error>" + ex.Message);
    }
    finally
    {
        sqlconn.Close();
    }
}

static void TVPsInsert()
{
    Console.WriteLine("使用简称TVPs插入数据");
    Stopwatch sw = new Stopwatch();
    for (int i = 0; i < 10; i++)
    {
        DataTable dt = GetTableSchema();
        for (int j = i * 100; j < (i + 1) * 100; j++)
        {
            DataRow r = dt.NewRow();
            r[0] = j;
            r[1] = string.Format("{0}", i * j);
            dt.Rows.Add(r);
        }
        sw.Start();
        TbaleValuedToDB(dt);
        sw.Stop();
        Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));
    }
    Console.ReadLine();  
}

结论

插入100w条记录,预计需要11s多

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以通过以下步骤将Oracle数据写入SQL Server: 1. 使用Oracle的OLEDB提供程序连接到Oracle数据库。 ```c# string connString = "Provider=OraOLEDB.Oracle;Data Source=OracleDB;User ID=Username;Password=Password"; OleDbConnection conn = new OleDbConnection(connString); ``` 2. 使用SQL Server的.NET提供程序连接SQL Server数据库。 ```c# string connString = "Data Source=SqlServerDB;Initial Catalog=DatabaseName;Integrated Security=True"; SqlConnection conn = new SqlConnection(connString); ``` 3. 使用OracleDataAdapter将数据从Oracle中检索出来。 ```c# string query = "SELECT * FROM OracleTable"; OleDbDataAdapter adapter = new OleDbDataAdapter(query, conn); DataTable dataTable = new DataTable(); adapter.Fill(dataTable); ``` 4. 使用SqlBulkCopy将数据写入SQL Server。 ```c# SqlBulkCopy bulkCopy = new SqlBulkCopy(conn); bulkCopy.DestinationTableName = "SqlTable"; bulkCopy.WriteToServer(dataTable); ``` 完整的代码如下: ```c# string oracleConnString = "Provider=OraOLEDB.Oracle;Data Source=OracleDB;User ID=Username;Password=Password"; string sqlServerConnString = "Data Source=SqlServerDB;Initial Catalog=DatabaseName;Integrated Security=True"; using (OleDbConnection oracleConn = new OleDbConnection(oracleConnString)) { oracleConn.Open(); using (SqlConnection sqlServerConn = new SqlConnection(sqlServerConnString)) { sqlServerConn.Open(); string query = "SELECT * FROM OracleTable"; using (OleDbDataAdapter adapter = new OleDbDataAdapter(query, oracleConn)) { DataTable dataTable = new DataTable(); adapter.Fill(dataTable); using (SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlServerConn)) { bulkCopy.DestinationTableName = "SqlTable"; bulkCopy.WriteToServer(dataTable); } } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值