我正在寻找一种方法来更新指定的SQL表(tr__Transaction)上的一些值,并将一些值插入到历史表(tr_History)中,同时(在单个查询中)描述更新的内容(字符串值),而不使用循环和触发器.

这不是我设计的数据库,但它是我正在处理的现有数据库.例如,我正在用tr_ShippingMethodId列中的新值更新(1,3,5)集中的现有记录.

更新了3行,现在我想向这tr_History个表中插入与我的示例查询相对应的新记录.

以下是我的样例代码:

DECLARE @tr__Transaction TABLE (tr_Id int, tr_ShippingMethodId int) -- table with transactions (online sale)

INSERT INTO @tr__Transaction (tr_Id, tr_ShippingMethodId) 
VALUES (1, 2), (2, 2), (3, 9), (4, 8), (5, 0)

DECLARE @tr_History TABLE 
                    (
                        th_Id INT, 
                        th_TransId INT, 
                        th_Time DATETIME, 
                        th_Entry NVARCHAR(255)
                    ) -- table with history log (what changed made on transaction)

DECLARE @TrIdsToUpdate TABLE (trIdToUpdate int) -- table with ids to update

INSERT INTO @TrIdsToUpdate VALUES (1, 3, 5)

UPDATE @tr__Transaction 
SET tr_ShippingMethodId = 99 
WHERE tr_Id IN (SELECT trIdToUpdate FROM @TrIdsToUpdate)

INSERT INTO @tr_History (th_Id, th_TransId, th_Time, th_Entry) 
VALUES (spGetId(tr_History), 1, GETDATE(), 'Record 1 changed shipping method from 2 to 99')

INSERT INTO @tr_History (th_Id, th_TransId, th_Time, th_Entry) 
VALUES (spGetId(tr_History), 3, GETDATE(), 'Record 3 changed shipping method from 9 to 99')

INSERT INTO @tr_History (th_Id, th_TransId, th_Time, th_Entry) 
VALUES (spGetId(tr_History), 5, GETDATE(), 'Record 5 changed shipping method from 0 to 99')

在这个查询中,我必须使用spGetId(tr_History)存储过程,它返回一个要插入的空闲ID(这是它最初设计的方式).

我还使用了3个INSERT命令来演示我想要实现的目标,但是使用@TrIdsToUpdate表和单个INSERT.

有什么建议要怎么做吗?

推荐答案

你可以用OUTPUT从句.

DECLARE @tr__Transaction TABLE (tr_Id int PRIMARY KEY, tr_ShippingMethodId int); -- table with transactions (online sale)

INSERT INTO @tr__Transaction (tr_Id, tr_ShippingMethodId) 
VALUES (1, 2), (2, 2), (3, 9), (4, 8), (5, 0);

DECLARE @tr_History TABLE 
                    (
                        th_Id INT IDENTITY PRIMARY KEY, 
                        th_TransId INT, 
                        th_Time DATETIME, 
                        th_Entry NVARCHAR(255)
                    ); -- table with history log (what changed made on transaction)

DECLARE @TrIdsToUpdate TABLE (trIdToUpdate int PRIMARY KEY); -- table with ids to update

INSERT INTO @TrIdsToUpdate VALUES (1), (3), (5);

UPDATE @tr__Transaction
SET tr_ShippingMethodId = 99
  OUTPUT
    inserted.tr_ID,
    GETDATE(),
    CONCAT('Record ', inserted.tr_ID, ' changed shipping method from ', deleted.tr_ShippingMethodId, ' to ', inserted.tr_ShippingMethodId )
  INTO @tr_History
    (th_TransId, th_Time, th_Entry)
WHERE tr_Id IN (SELECT u.trIdToUpdate FROM @TrIdsToUpdate u);

我不知道您的spGetId函数在做什么,但这可能不是一个好主意,您应该只使用IDENTITYSEQUENCE列.

如图所示,出于性能原因,将主键也放在表变量上可能是明智的.

Sql相关问答推荐

创建每小时重置的序列号

Oracle SQL中的累计总数

我可以将INSERT语句与SELECT一起使用来创建条件吗?

通过 Select 值的顺序进行排序ClickHouse

Select 起始参数和截止参数之间的间隔,包括与期间重叠的参数

PostgreSQL中的合并命令是原子的,还是需要一些类似于SQL Server版本的内容?

编写一个SQL查询来返回收视率较高的类型,并取这些收视率的平均值,我该如何做呢?

UPDATE查询中的乐观锁

返回找到的最小和最大row_number()spark SQL

如何隐藏聚合JSON数组元素的键

从列中提取子字符串的ORDER BY CASE语句

根据Rails活动记录中时间戳/日期时间的时间部分从PostgreSQL中提取记录

将一个数组反嵌套到另外两个数组SQL中(Athena/presto)

需要从键-值对数据中提取值

如何使用jsonn_populate_record()插入到包含IDENTITY列的表中

创建具有多个子查询的 SQL 视图

汇总具有连续日期范围的行

oracle中多行的跨日期范围的交集

SQL Select 最大并获取列名

在 Athena / Presto 中提取 JSON 对象以获取动态密钥