我已经阅读了几十个帖子,其中许多帖子可追溯到几年前,并且无法提供一种现代,安全且可靠的方式来将数千条记录中的特殊值更新为单个查询。
我遍历表中的所有记录,根据一些特殊逻辑确定DateTime值,然后运行这个简单的查询来更新该值...超过3500次。通过电线进行了大量的旅行。
UPDATE ScheduleTickets
SET ScheduledStartUTC = @ScheduledStartUTC
WHERE ScheduleId = @ScheduleId AND PatchSessionId = @PatchSessionId
通过保存和使用DataTable,我看到了不浪费内存的评论。我见过使用StringBuilder动态创建更新查询但感觉不安全/脏的解决方案。当然,整个过程不到一分钟,但必须有更好的方法。
因此,在计算出DateTime值后,我调用了......
UpdateScheduleTicketStart(ScheduleId, PatchSessionId, scheduledDateTime);
看起来像这样......
private static void UpdateScheduleTicketStart(long scheduleId, long patchSessionId, DateTime scheduledStartUTC)
{
using (SqlConnection c = ConnectVRS())
{
SqlCommand cmd = new SqlCommand(@"
UPDATE ScheduleTickets
SET ScheduledStartUTC = @ScheduledStartUTC
WHERE ScheduleId = @ScheduleId AND PatchSessionId = @PatchSessionId
", c);
cmd.Parameters.Add("@ScheduleId", SqlDbType.BigInt).Value = scheduleId;
cmd.Parameters.Add("@PatchSessionId", SqlDbType.BigInt).Value = patchSessionId;
cmd.Parameters.Add("@ScheduledStartUTC", SqlDbType.VarChar).Value = scheduledStartUTC;
cmd.ExecuteNonQuery();
}
}
如何在一次调用中将所有值传递给SQL Server,或者如何创建单个SQL查询以便一次性执行更新?
答案 0 :(得分:3)
如果值在另一个表中,请使用join
:
UPDATE st
SET ScheduledStartUTC = ot.ScheduledStartUTC
FROM ScheduleTickets st JOIN
OtherTable ot
ON st.ScheduleId = ot.ScheduleId AND st.PatchSessionId = ot.PatchSessionId;
您没有指定特殊逻辑,但您可以在SQL中表达它。
答案 1 :(得分:3)
很多人建议使用TableValueParameter,我同意这是一个很好的方法。以下是如何做到这一点的示例:
首先在SQL Server中创建TVP和存储过程
CREATE TYPE [dbo].[SchdeuleTicketsType] As Table
(
ScheduledStartUTC DATETIME NOT NULL
, ScheduleId INT NOT NULL
, PatchSessionId INT NOT NULL
)
CREATE PROCEDURE [dbo].[usp_UpdateTickets]
(
@ScheduleUpdates As [dbo].[SchdeuleTicketsType] Readonly
)
AS
Begin
UPDATE t1
SET t1.ScheduledStartUTC = t2.ScheduledStartUTC
FROM ScheduleTickets AS t1
INNER JOIN @ScheduleUpdates AS t2
ON t1.ScheduleId = t2.ScheduleId AND
t1.PatchSessionId = t2.PatchSessionId
End
)
下一步修改代码以填充表格并将其作为参数传递给存储的proc:
private void Populate()
{
DataTable dataTable = new DataTable("SchdeuleTicketUpdates");
//we create column names as per the type in DB
dataTable.Columns.Add("ScheduledStartUTC", typeof(DateTime));
dataTable.Columns.Add("ScheduleId", typeof(Int32));
dataTable.Columns.Add("PatchSessionId", typeof(Int32));
//write you loop to populate here
//call the stored proc
using (var conn = new SqlConnection(connString))
{
var command = new SqlCommand("[usp_UpdateTickets]");
command.CommandType = CommandType.StoredProcedure;
var parameter = new SqlParameter();
//The parameter for the SP must be of SqlDbType.Structured
parameter.ParameterName = "@ScheduleUpdates";
parameter.SqlDbType = System.Data.SqlDbType.Structured;
parameter.Value = dataTable;
command.Parameters.Add(parameter);
command.ExecuteNonQuery();
}
}