I have implemented an audit trail framework based on the information provided by the first answer to the following post:
SQL Server history table - populate through
Ran into a similar problem... figured it out this way... may not be the most elegant solution but works for the compliance guys... So here goes...
Based on the solution given here
The xml is extracted with FOR XML from the trigger that updated the table... The "OldValues" come from the DELETED table and the "NewValues" from the INSERTED table... so the final xml looks like this...
DECLARE @x XML= '
OldValues
5
TEST_TIE
OldValues
4
RP_TIE
OldValues
3
ERR_TIE
NewValues
5
TEST_TIE
A
NewValues
4
RP_TIE
A
NewValues
3
ERR_TIE
A
'
declare @timestamp datetime2= SYSDATETIME()
select
ID = identity(int,1,1),
T.N.value('local-name(.)', 'nvarchar(100)') as NodeName,
T.N.value('../ID[1]','nvarchar(100)') AS table_ID,
T.N.value('.', 'nvarchar(100)') as OldValue
INTO #old
from @x.nodes('//UpdatedColumns/*') as T(N)
WHERE T.N.value('../trType[1]', 'nvarchar(100)') ='OldValues'
select
ID = identity(int,1,1),
T.N.value('local-name(.)', 'nvarchar(100)') as NodeName,
T.N.value('../ID[1]','nvarchar(100)') AS Table_ID,
T.N.value('.', 'nvarchar(100)') as NewValue
into #new
from @x.nodes('//UpdatedColumns/*') as T(N)
WHERE T.N.value('../trType[1]', 'nvarchar(100)') ='NewValues'
SELECT n.table_ID, n.NodeName, o.OldValue, n.NewValue,@timestamp as transation_time FROM #new n
left outer JOIN #old o ON n.NodeName = o.NodeName AND n.ID = o.ID
WHERE isnull(o.[OldValue],'') <> isnull(n.[newValue],'') AND n.NodeName <> 'trType'
DROP TABLE #new,#old
GO