简体   繁体   English

SQL 根据找到的最后记录更新或插入

[英]SQL update or insert based on last record found

Quick background: Process equipment vendor wrote code to update DB with results of process.快速背景:过程设备供应商编写代码以使用过程结果更新数据库。 Data essentially is: (Order #, Result, Qty) except that the Qty is always 1, and when the batch is large, I get a lot of identical records.数据本质上是:(Order #, Result, Qty) 除了Qty总是1,当batch很大的时候,我得到很多相同的记录。 Vendor software update is not an option.供应商软件更新不是一个选项。 DB update by vendor is done by calling a stored procedure.供应商的数据库更新是通过调用存储过程完成的。

What I want to do in the stored procedure, is if the last record for a specific Order # has identical result as the record currently being inserted, then +1 to Qty of last record (and no new record).我想在存储过程中做的是,如果特定订单 # 的最后一条记录与当前插入的记录具有相同的结果,则 +1 到最后一条记录的数量(并且没有新记录)。

In my research, all examples have included the Result as a part of the Where, which would always combine like results, but my order of results is important.在我的研究中,所有示例都将结果作为 Where 的一部分包含在内,它总是会组合类似的结果,但我的结果顺序很重要。 If 3 have result X1, 1 has result X2, and another 2 have result X1, then I need 3 records when finished:如果 3 个有结果 X1,1 个有结果 X2,另外 2 个有结果 X1,那么完成后我需要 3 个记录:

Order  Result Qty 
101    X1     3
101    X2     1
101    X1     2

I also looked at using a cursor, but that seems to expect one to look through several records, and I will only be looking at one.我还查看了使用 cursor 的情况,但这似乎需要查看多个记录,而我只会查看一个。 CTE or a nested query seem possible, but I'm not clear how to achive. CTE 或嵌套查询似乎是可能的,但我不清楚如何实现。

In this case, I can assume that only one machine is processing 1 order, and updates for that order will have pleanty of time to complete before the next update.在这种情况下,我可以假设只有一台机器正在处理 1 个订单,并且在下一次更新之前对该订单的更新将有足够的时间完成。 But ideally the solution would be atomic and able to deal with overlapping update requests.但理想情况下,解决方案应该是原子的,并且能够处理重叠的更新请求。

What I am working towards, but don't know if it is the best path (@p variables are passed in, @l variables are used to store the last record):我正在努力的方向,但不知道它是否是最佳路径(传入@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

It seems you need to check to see if the update modified rows.看来您需要检查更新是否修改了行。 If not then insert.如果没有则插入。 In plain language the code says: "Try to update the LOG table if the order matches an order placed within the last 7 minutes. If it doesn't find a match then insert a new row with the CREATEDATE set to the current date."代码用通俗易懂的语言说:“如果订单与最近 7 分钟内下达的订单相匹配,请尝试更新 LOG 表。如果没有找到匹配项,则插入一个新行,并将 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());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM