在更新查询中查找所有更改的值

Find all changed values in update query

我有一个从源表更新目标表的查询,但前提是目标表中的字段为空或包含值“1899-12-30”。

Targettable 和 sourcetable 仅包含 nvarchar 字段。我对这些表的设计没有影响。任何看起来像日期的字符串仍应被视为字符串。

UPDATE targettable SET
 columnA=IIF(len(t.columnA) = 0 OR t.columnA = '1899-12-30', s.columnA,t.ColumnA)
,columnB=IIF(len(t.columnB) = 0 OR t.columnB = '1899-12-30', s.columnB,t.columnB)
,columnC=IIF(len(t.columnC) = 0 OR t.columnC = '1899-12-30', s.columnC,t.columnC)
FROM sourcetable s
LEFT JOIN targettable t

t.ColumnA = ''(空字符串)所以它 更新 为 s.columnA 其中包含 'foo'
t.ColumnB = 'something' 所以它 不会更新
t.ColumnC = '1899-12-30' 所以它 更新 为 s.columnC 其中包含 '1900-01-01'

现在我想要的是获取更改的值并像这样存储它们

TIME_OF_CHANGE | COLUMNNAME| OLD_VALUE | NEW_VALUE
2021-5-20 14:12 | ColumnA |  | foo
2021-5-20 14:12 | ColumnC | 1899-12-30| 1900-01-01

updatequery 非常有效,但我不知道如何转换此数据,以便将其写为

TIME_OF_CHANGE | COLUMNNAME| OLD_VALUE | NEW_VALUE

最后我是这样的:

declare @changeTime as datetime = getdate()

;WITH NEWDATA AS (
SELECT @changeTime AS modified, 'NEW' AS status, t.id AS primarykey
,columnA=IIF(len(t.columnA) = 0 OR t.columnA = '1899-12-30', s.columnA,t.ColumnA)
,columnB=IIF(len(t.columnB) = 0 OR t.columnB = '1899-12-30', s.columnB,t.columnB)
,columnC=IIF(len(t.columnC) = 0 OR t.columnC = '1899-12-30', s.columnC,t.columnC) 
FROM sourcetable s
INNER JOIN targettable t
WHERE t.columnA=IIF(len(t.columnA) = 0 OR t.columnA = '1899-12-30', s.columnA,t.ColumnA)
OR t.columnB=IIF(len(t.columnB) = 0 OR t.columnB = '1899-12-30', s.columnB,t.columnB)
OR t.columnC=IIF(len(t.columnC) = 0 OR t.columnC = '1899-12-30', s.columnC,t.columnC)
)
    
INSERT INTO tbl_CHANGES
SELECT * FROM NEWDATA

INSERT INTO tbl_CHANGES
SELECT @changeTime AS modified, 'OLD' AS status, t.id AS primarykey,* 
FROM targettable t
WHERE t.primarykey in (SELECT primarykey FROM tbl_CHANGES WHERE modified = @changeTime)

UPDATE targettable SET
 columnA=IIF(len(t.columnA) = 0 OR t.columnA = '1899-12-30', s.columnA,t.ColumnA)
,columnB=IIF(len(t.columnB) = 0 OR t.columnB = '1899-12-30', s.columnB,t.columnB)
,columnC=IIF(len(t.columnC) = 0 OR t.columnC = '1899-12-30', s.columnC,t.columnC)
FROM sourcetable s
LEFT JOIN targettable t

它存储每个已更改记录的 'OLD' 版本和“新”版本。 它不如最初设想的解决方案那么好,但它确实满足了能够看到更改内容的目标。 当然,所有这些都包含在一次交易中。这不是最好的或最聪明的(这不是生产)但有人可能会偶然发现这个问题并喜欢一个答案。