使用 BizTalk 2013r2 通过 WCF-SQL 存储过程进行 UPSERT
Using BizTalk 2013r2 to UPSERT via WCF-SQL stored procedure
我目前正在尝试为 SQL 数据库中的多个相关 table 编写规范模式,但在评估记录之前是否存在时,我遇到了 DUPLICATE KEY ID 冲突至 UPDATING/INSERTING.
BizTalk 每 5 分钟从学生管理系统接收一次更改记录,将它们映射到一个存储过程,然后调用该过程将更改写入我们的主数据库中的 5 tables。
我认为这是因为我在存储过程中使用了不正确的设计模式。
当前设计:
IF EXISTS (Select student_id FROM student_modules WHERE student_id @student_id and module_id = @module_id)
-- THEN UPDATE THE RECORD
ELSE
-- INSERT THE RECORD
逻辑上这是有道理的,但是因为 BizTalk 同时收到 2 条具有完全相同的学生和模块 ID 的更改记录,然后尝试为每条记录调用存储过程。
SQL 然后恐慌,因为在评估第一条消息中的逻辑时,它会尝试执行 INSERT,同时评估第二条消息中的相同逻辑 - 并告诉我我正在尝试插入 DUPLICATE KEY。
我已经尝试使用我在下面 link(下面的设计)中找到的 UPSERT 模式,但这似乎完全锁定了 student_modules table。
BEGIN TRANSACTION;
UPDATE dbo.t WITH (UPDLOCK, SERIALIZABLE) SET val = @val WHERE [key] = @key;
IF @@ROWCOUNT = 0
BEGIN
INSERT dbo.t([key], val) VALUES(@key, @val);
END
COMMIT TRANSACTION;
https://sqlperformance.com/2020/09/locking/upsert-anti-pattern
是否有我缺少的更简洁的方法?
您可以使用 MERGE Transact-SQL 命令
INSERT tbl_A (col, col2)
SELECT col, col2
FROM tbl_B
WHERE NOT EXISTS (SELECT col FROM tbl_A A2 WHERE A2.col = tbl_B.col);
您还需要考虑更改您的 Orchestration 以便它订阅同一学生 ID 的进一步更新(单例类型模式)或将您的发送端口设置为有序交付,以防止尝试更新相同的学生 ID同时记录。
我目前正在尝试为 SQL 数据库中的多个相关 table 编写规范模式,但在评估记录之前是否存在时,我遇到了 DUPLICATE KEY ID 冲突至 UPDATING/INSERTING.
BizTalk 每 5 分钟从学生管理系统接收一次更改记录,将它们映射到一个存储过程,然后调用该过程将更改写入我们的主数据库中的 5 tables。
我认为这是因为我在存储过程中使用了不正确的设计模式。
当前设计:
IF EXISTS (Select student_id FROM student_modules WHERE student_id @student_id and module_id = @module_id)
-- THEN UPDATE THE RECORD
ELSE
-- INSERT THE RECORD
逻辑上这是有道理的,但是因为 BizTalk 同时收到 2 条具有完全相同的学生和模块 ID 的更改记录,然后尝试为每条记录调用存储过程。 SQL 然后恐慌,因为在评估第一条消息中的逻辑时,它会尝试执行 INSERT,同时评估第二条消息中的相同逻辑 - 并告诉我我正在尝试插入 DUPLICATE KEY。 我已经尝试使用我在下面 link(下面的设计)中找到的 UPSERT 模式,但这似乎完全锁定了 student_modules table。
BEGIN TRANSACTION;
UPDATE dbo.t WITH (UPDLOCK, SERIALIZABLE) SET val = @val WHERE [key] = @key;
IF @@ROWCOUNT = 0
BEGIN
INSERT dbo.t([key], val) VALUES(@key, @val);
END
COMMIT TRANSACTION;
https://sqlperformance.com/2020/09/locking/upsert-anti-pattern
是否有我缺少的更简洁的方法?
您可以使用 MERGE Transact-SQL 命令
INSERT tbl_A (col, col2)
SELECT col, col2
FROM tbl_B
WHERE NOT EXISTS (SELECT col FROM tbl_A A2 WHERE A2.col = tbl_B.col);
您还需要考虑更改您的 Orchestration 以便它订阅同一学生 ID 的进一步更新(单例类型模式)或将您的发送端口设置为有序交付,以防止尝试更新相同的学生 ID同时记录。