【问题标题】:SQLBulk WritetoServer from JSON来自 JSON 的 SQLBulk WritetoServer
【发布时间】:2026-02-20 20:15:01
【问题描述】:

您好,我正在尝试从JSON to SQL Server 输入大量数据,因此根据我的研究,我可以将JSON to DataTable and then use SQLBulk 转换为使用WriteToSever(dataTable) 将数据写入服务器。这是最好的方法吗?

我怎样才能通过这种方式为每一行插入提取Scope_identity()

【问题讨论】:

    标签: c# sql-server sql-server-2008 bulkinsert sqlbulkcopy


    【解决方案1】:

    从批量插入命令中提取作用域标识实际上是不可能的。如果你想在插入语句中准确地取回每个 scope_identity() 值,你真的必须单独插入每条记录。

    不过,您也可以考虑使用表参数插入(我在这里写了一篇关于它的文章:http://www.altdevblogaday.com/2012/05/16/sql-server-high-performance-inserts/)。

    首先,创建表格插入类型:

    CREATE TYPE item_drop_bulk_table_rev4 AS TABLE (
        item_id BIGINT,
        monster_class_id INT,
        zone_id INT,
        xpos REAL,
        ypos REAL,
        kill_time datetime
    )
    

    其次,创建一个插入数据的过程:

    CREATE PROCEDURE insert_item_drops_rev4
        @mytable item_drop_bulk_table_rev4 READONLY
    AS
    
    BEGIN TRANSACTION
    
    -- Lookup the current ID
    DECLARE @id_marker bigint
    SELECT @id_marker = MAX(primary_key_column) FROM item_drops_rev4 
    
    -- Insert all the data
    INSERT INTO item_drops_rev4 
        (item_id, monster_class_id, zone_id, xpos, ypos, kill_time)
    SELECT 
        item_id, monster_class_id, zone_id, xpos, ypos, kill_time 
    FROM 
        @mytable
    
    -- Return back the identity values
    SELECT * FROM item_drops_rev4 WHERE primary_key_column > @id_marker
    
    COMMIT TRANSACTION
    

    第三,编写C#代码来插入这个数据:

    DataTable dt = new DataTable();
    dt.Columns.Add(new DataColumn("item_id", typeof(Int64)));
    dt.Columns.Add(new DataColumn("monster_class_id", typeof(int)));
    dt.Columns.Add(new DataColumn("zone_id", typeof(int)));
    dt.Columns.Add(new DataColumn("xpos", typeof(float)));
    dt.Columns.Add(new DataColumn("ypos", typeof(float)));
    dt.Columns.Add(new DataColumn("timestamp", typeof(DateTime)));
    
    for (int i = 0; i < MY_INSERT_SIZE; i++) {
        dt.Rows.Add(new object[] { item_id, monster_class_id, zone_id, xpos, ypos, DateTime.Now });
    }
    
    // Now we&#039;re going to do all the work with one connection!
    using (SqlConnection conn = new SqlConnection(my_connection_string)) {
        conn.Open();
        using (SqlCommand cmd = new SqlCommand("insert_item_drops_rev4", conn)) {
            cmd.CommandType = CommandType.StoredProcedure;
    
            // Adding a "structured" parameter allows you to insert tons of data with low overhead
            SqlParameter param = new SqlParameter("@mytable", SqlDbType.Structured);
            param.Value = dt;
            cmd.Parameters.Add(param);
            SqlDataReader dr = cmd.ExecuteReader()
            // TODO: Read back in the objects, now attached to their primary keys
        }
    }
    

    现在,理论上,您只能取回单个“id 标记”。但是,我不相信每个版本的 SQL Server 都会始终以线性顺序从数据表插入中插入记录,因此我认为检索回整个数据批次更安全。

    【讨论】: