结合这个删除所有不合格项并启用所有合格项的SQL更新操作?

问题描述 投票:0回答:1

我正在执行以下意图:

我的查询中有一个有效合格的凭证代码列表/表格。 我想将此列表中的所有学生优惠券标记为已删除 = 0,并且如果它们出现在列表中,则将 is_applied 标记为 true。

对于student_header 表的给定外键student_header_id 下未出现的所有其他student_vouchers,我想将它们标记为已应用的 false 已删除。

以下代码执行得足够好,但是我似乎在与 Student_vouchers 交互的其他事务方面遇到了大量死锁。所以我认为如果我可以将其合并到单个更新操作中会更好,这可能吗?这样的改变是否有助于解决僵局?

DECLARE @applied_voucher_table table
                                       (
            value nvarchar(max)
                                       );    
-- REMOVE INVALID STUDENT VOUCHERS
UPDATE student_vouchers
    SET is_applied   = 0,
        deleted      = 1,
        deleted_date = GETDATE(),
        edited_date = GETDATE()
    OUTPUT INSERTED.voucher_code INTO @DeletedVouchers
    WHERE student_header_id = @HEADERID AND deleted = 0;

DECLARE @AppliedVouchers TABLE (voucher_code NVARCHAR(MAX));
IF (
                (
                    SELECT COUNT(*)
                    FROM @applied_voucher_table
                    WHERE value IS NOT NULL
                    AND value != '') > 0
                )
BEGIN
                --UPDATE VALID VOUCHERS
    UPDATE student_vouchers
        SET is_applied   = 1,
            deleted      = 0,
            edited_date  = GETDATE(),
        OUTPUT INSERTED.voucher_code INTO @AppliedVouchers
        WHERE student_header_id = @HEADERID
          AND voucher_code IN
             (SELECT value
              FROM @applied_voucher_table
              WHERE value IS NOT NULL AND value != '')
          AND id IN (SELECT id
              FROM @applied_voucher_table);
 END;
student_vouchers (
  id,
  student_header_id,
  voucher_code,
  is_applied,
  deleted,
  deleted_date,
  edited_date

如果有不清楚的地方请告诉我! 请注意,我收到此列表 @DeletedVouchers 很重要,但是最好也有 @AppliedVouchers 列表,它们都发送到远程进程。

sql sql-server stored-procedures sql-update deadlock
1个回答
0
投票

您可以使用左连接和一些

CASE
IIF
表达式将两个表和更新合并为一个表。

DECLARE @UpdatedVouchers TABLE (voucher_code NVARCHAR(MAX) NOT NULL, is_deleted bit NOT NULL);

UPDATE sv
SET is_applied   = IIF(avt.id IS NOT NULL, CAST(1 AS bit), CAST(0 AS bit)),
    deleted      = IIF(avt.id IS NOT NULL, CAST(0 AS bit), CAST(1 AS bit)),
    deleted_date = IIF(avt.id IS NOT NULL, sv.deleted_date, GETDATE())
    edited_date = GETDATE()
OUTPUT inserted.deleted, inserted.voucher_code
INTO @UpdatedVouchers (voucher_code, is_deleted)
FROM student_vouchers sv
LEFT JOIN @applied_voucher_table av
    ON avt.value = sv.voucher_code
   AND avt.value != ''
   AND avt.id = sv.id
WHERE sv.student_header_id = @HEADERID
  AND (sv.deleted = 0 OR avt.id IS NOT NULL);

请注意,左连接中的语义与原始语义略有不同,但我怀疑无论如何这是更正确的。在原始版本中,

id
value
可以从不同的行进行匹配,看起来应该是一个带有两个内部
EXISTS
条件的
WHERE
。在此版本中,它们需要来自一行。

© www.soinside.com 2019 - 2024. All rights reserved.