.NET中如何结合GO语句使用参数化查询?
解决方案:无需GO语句,用参数化批量插入优化并发与锁
首先明确:GO不是必须的,它只是SQL Server客户端工具(比如SSMS)用来拆分脚本的批处理分隔符,并非T-SQL原生语法,数据库引擎本身不识别GO。你的核心需求是优化并发、减少锁表中断,应该从批量插入的效率和事务管理入手,而非依赖GO。
为什么GO帮不了你
GO会把脚本拆分成多个独立批处理,每个批处理单独执行,反而会增加数据库往返次数,每个批处理的锁都要单独申请释放,间隙期更容易被其他进程抢占锁,反而可能加剧锁冲突,完全达不到你想要的效果。
用SqlCommand实现高效参数化批量插入的两种方案
方案1:表值参数(推荐,适合大量行插入)
这是SQL Server最高效的批量参数化插入方式,只需一次数据库往返,锁持有时间最短,同时完全避免SQL注入。
第一步:在SQL Server创建表类型
CREATE TYPE [dbo].[TableType_Insert] AS TABLE( [id] INT, -- 匹配你的表字段类型 [type] INT, [value] VARCHAR(100) -- 替换为实际字段类型 )
第二步:C#代码实现
// 构造要插入的数据表 DataTable insertData = new DataTable(); insertData.Columns.Add("id", typeof(int)); insertData.Columns.Add("type", typeof(int)); insertData.Columns.Add("value", typeof(string)); // 添加需要插入的行 insertData.Rows.Add(id, 10, value1); insertData.Rows.Add(id, 15, value2); insertData.Rows.Add(id, 20, value3); // 可继续添加更多行... using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["context"].ConnectionString)) { string query = @" INSERT INTO [dbo].[table_name] (id, type, value) SELECT id, type, value FROM @InsertData "; SqlCommand sqlCommand = new SqlCommand(query, connection); // 配置表值参数 SqlParameter tvpParam = sqlCommand.Parameters.AddWithValue("@InsertData", insertData); tvpParam.SqlDbType = SqlDbType.Structured; tvpParam.TypeName = "[dbo].[TableType_Insert]"; // 指定刚才创建的表类型 connection.Open(); sqlCommand.ExecuteNonQuery(); }
方案2:多行VALUES语法(适合少量行插入)
把多个INSERT合并为单个INSERT语句,用多行VALUES语法,同样是单次批处理执行,参数化简单。
string query = @" INSERT INTO [dbo].[table_name] (id, type, value) VALUES (@id, 10, @value1), (@id, 15, @value2), (@id, 20, @value3) -- 可继续添加更多行... "; using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["context"].ConnectionString)) { SqlCommand sqlCommand = new SqlCommand(query, connection); sqlCommand.Parameters.AddWithValue("@id", id); sqlCommand.Parameters.AddWithValue("@value1", value1); sqlCommand.Parameters.AddWithValue("@value2", value2); sqlCommand.Parameters.AddWithValue("@value3", value3); // 对应添加更多参数... connection.Open(); sqlCommand.ExecuteNonQuery(); }
额外优化:事务管理
如果需要保证所有插入要么全部成功要么全部失败,可以把执行逻辑包裹在显式事务中,减少锁的持有时间(相比自动提交每个INSERT):
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["context"].ConnectionString)) { connection.Open(); using (SqlTransaction transaction = connection.BeginTransaction()) { try { // 这里放入上述任意一种方案的SqlCommand执行逻辑 sqlCommand.Transaction = transaction; sqlCommand.ExecuteNonQuery(); transaction.Commit(); } catch (Exception) { transaction.Rollback(); throw; } } }
内容的提问来源于stack exchange,提问作者Seth R.
相关产品推荐
相关产品推荐

