SQL 根据找到的最后一条记录更新或插入
SQL update or insert based on last record found
快速背景:过程设备供应商编写代码以使用过程结果更新数据库。数据本质上是:(Order #, Result, Qty) 除了Qty总是1,当batch很大的时候,我得到很多相同的记录。供应商软件更新不是一个选项。供应商的数据库更新是通过调用存储过程完成的。
我想在存储过程中做的是,如果特定订单 # 的最后一条记录与当前插入的记录具有相同的结果,则最后一条记录的数量 +1(没有新记录)。
在我的研究中,所有示例都将结果作为 Where 的一部分包含在内,它总是会组合类似的结果,但我的结果顺序很重要。如果3个有结果X1,1个有结果X2,另外2个有结果X1,那么完成后我需要3条记录:
Order Result Qty
101 X1 3
101 X2 1
101 X1 2
我也看过使用游标,但这似乎需要一个人浏览几条记录,而我只会看一条。 CTE 或嵌套查询似乎是可能的,但我不清楚如何实现。
在这种情况下,我可以假设只有一台机器正在处理 1 个订单,并且在下一次更新之前有足够的时间完成该订单的更新。但理想情况下,解决方案应该是原子的,并且能够处理重叠的更新请求。
我正在努力的方向,但不知道这是不是最好的路径(传入@p变量,@l变量用于存储最后一条记录):
select top(1) @lOrder = OrderCol,
@lResult = ResultCol,
@lCreateDate = CREATEDATE
from dbo.LOG
where OrderCol = @pOrder
order by CREATEDATE desc
-- make sure the record is no more than x min old, and every other passed value matches
if ( @lOrder = @pOrder
and @lResult = @pResult
and @lCreateDate > DATEADD(minute, -7, GETDATE())
)
begin
Update dbo.LOG
set [QtyCol] += @pQty
where @lOrder = OrderCol
and @lCreateDate = CREATEDATE
end
else
begin
INSERT INTO dbo.LOG
([OrderCol], [QtyCol], [ResultCol], CREATEDATE )
VALUES(@pOrder, @pQty, @pResult, GETDATE());
end
看来您需要检查更新是否修改了行。如果没有则插入。用简单的语言,代码说:“如果订单与最近 7 分钟内下达的订单匹配,请尝试更新 LOG table。如果找不到匹配项,则插入一个新行,并将 CREATEDATE 设置为当前日期。
select top(1) @lOrder = OrderCol,
@lResult = ResultCol,
@lCreateDate = CREATEDATE
from dbo.LOG
where OrderCol = @pOrder
order by CREATEDATE desc;
Update dbo.LOG
set [QtyCol] += @pQty
where OrderCol = @lOrder
and ResultCol = @lResult
and ResultCol = @pResult
and CREATEDATE >= dateadd(minute, -7, getdate());
if @@rowcount=0
insert INTO dbo.LOG([OrderCol], [QtyCol], [ResultCol], CREATEDATE )
VALUES(@pOrder, @pQty, @pResult, GETDATE());
快速背景:过程设备供应商编写代码以使用过程结果更新数据库。数据本质上是:(Order #, Result, Qty) 除了Qty总是1,当batch很大的时候,我得到很多相同的记录。供应商软件更新不是一个选项。供应商的数据库更新是通过调用存储过程完成的。
我想在存储过程中做的是,如果特定订单 # 的最后一条记录与当前插入的记录具有相同的结果,则最后一条记录的数量 +1(没有新记录)。
在我的研究中,所有示例都将结果作为 Where 的一部分包含在内,它总是会组合类似的结果,但我的结果顺序很重要。如果3个有结果X1,1个有结果X2,另外2个有结果X1,那么完成后我需要3条记录:
Order Result Qty
101 X1 3
101 X2 1
101 X1 2
我也看过使用游标,但这似乎需要一个人浏览几条记录,而我只会看一条。 CTE 或嵌套查询似乎是可能的,但我不清楚如何实现。
在这种情况下,我可以假设只有一台机器正在处理 1 个订单,并且在下一次更新之前有足够的时间完成该订单的更新。但理想情况下,解决方案应该是原子的,并且能够处理重叠的更新请求。
我正在努力的方向,但不知道这是不是最好的路径(传入@p变量,@l变量用于存储最后一条记录):
select top(1) @lOrder = OrderCol,
@lResult = ResultCol,
@lCreateDate = CREATEDATE
from dbo.LOG
where OrderCol = @pOrder
order by CREATEDATE desc
-- make sure the record is no more than x min old, and every other passed value matches
if ( @lOrder = @pOrder
and @lResult = @pResult
and @lCreateDate > DATEADD(minute, -7, GETDATE())
)
begin
Update dbo.LOG
set [QtyCol] += @pQty
where @lOrder = OrderCol
and @lCreateDate = CREATEDATE
end
else
begin
INSERT INTO dbo.LOG
([OrderCol], [QtyCol], [ResultCol], CREATEDATE )
VALUES(@pOrder, @pQty, @pResult, GETDATE());
end
看来您需要检查更新是否修改了行。如果没有则插入。用简单的语言,代码说:“如果订单与最近 7 分钟内下达的订单匹配,请尝试更新 LOG table。如果找不到匹配项,则插入一个新行,并将 CREATEDATE 设置为当前日期。
select top(1) @lOrder = OrderCol,
@lResult = ResultCol,
@lCreateDate = CREATEDATE
from dbo.LOG
where OrderCol = @pOrder
order by CREATEDATE desc;
Update dbo.LOG
set [QtyCol] += @pQty
where OrderCol = @lOrder
and ResultCol = @lResult
and ResultCol = @pResult
and CREATEDATE >= dateadd(minute, -7, getdate());
if @@rowcount=0
insert INTO dbo.LOG([OrderCol], [QtyCol], [ResultCol], CREATEDATE )
VALUES(@pOrder, @pQty, @pResult, GETDATE());