我们目前在存储过程中的INSERT和UPDATEs上使用OUTPUT,以连接在一起的字符串形式转换为XML,以跟踪已更改的内容。然后将该XML放入UDT中,并传递给另一个过程,在该过程中将其解析并放入物理跟踪表中。
我们正在跟踪表的名称,行的PK值已更改,列已更改,旧值和新值,用于同时标识值的批处理ID以及谁/何时改变了。
解析XML以便可以将其放入实际跟踪表的过程是一个重要的性能瓶颈。我正在尝试提出替代方法,但是我很简短。我唯一想到的可能是OUTPUT查询上的某种PIVOT,用于将值以其本机形式而不是串联为XML的形式放入UDT。
这是UPDATE末尾的OUTPUT语句的示例
DECLARE @TrackingColumnChange TrackingColumnChangeType
OUTPUT
'SomeTable',
@SessionId,
@statementId,
INSERTED.TransactionMortgageId,
CAST('<Columns>' +
'<Column>' +
'<ColumnName>SomeColumn1</ColumnName>' +
'<OldValue>' + ISNULL(CAST(DELETED.SomeColumn1 AS VARCHAR(50)), '"Blank"') + '</OldValue>' +
'<NewValue>' + ISNULL(CAST(INSERTED.SomeColumn1 AS VARCHAR(50)), '"Blank"') + '</NewValue>' +
'</Column>' +
'<Column>' +
'<ColumnName>SomeColumn2</ColumnName>' +
'<OldValue>' + ISNULL(CAST(DELETED.SomeColumn2 AS VARCHAR(50)), '"Blank"') + '</OldValue>' +
'<NewValue>' + ISNULL(CAST(INSERTED.SomeColumn2 AS VARCHAR(50)), '"Blank"') + '</NewValue>' +
'</Column>' +
'</Columns>' AS XML),
NULL,
NULL,
@spSystemUserLoginId
INTO @TrackingColumnChange (TableName,
SessionId,
StatementId,
PrimaryKey,
TrackingData,
ContextReferenceId,
ContextReferenceType,
CreatorId
)
然后解析它的查询如下:
CREATE TABLE #Tracking ([TableName] [nvarchar](128) NOT NULL,
[ColumnName] [nvarchar](128) NOT NULL,
[SessionId] [bigint] NOT NULL,
[StatementId] [bigint] NOT NULL,
[PrimaryKey] [int] NOT NULL,
[OldValue] [varchar](max) NULL,
[NewValue] [varchar](max) NULL,
[ContextReferenceId] BIGINT NULL,
[ContextReferenceType] [nvarchar](128) NULL,
[CreatorId] [int] NOT NULL
)
INSERT INTO #Tracking (TableName,
ColumnName,
SessionId,
StatementId,
PrimaryKey,
OldValue,
NewValue,
ContextReferenceId,
ContextReferenceType,
CreatorId
)
SELECT TrackingColumnChange.TableName,
ref.value('(ColumnName)[1]', 'NVARCHAR(128)'),
TrackingColumnChange.SessionId,
TrackingColumnChange.StatementId,
TrackingColumnChange.PrimaryKey,
ref.value('(OldValue)[1]', 'VARCHAR(MAX)'),
ref.value('(NewValue)[1]', 'VARCHAR(MAX)'),
TrackingColumnChange.ContextReferenceId,
TrackingColumnChange.ContextReferenceType,
TrackingColumnChange.CreatorId
FROM @TrackingColumnChange TrackingColumnChange
CROSS APPLY TrackingColumnChange.TrackingData.nodes('Columns/Column') TrackingData(ref)
在实际插入Tracking表之前,该proc会做更多的事情。但是,XQuery是执行计划的99.9%-100%。我认为,理想情况下,最好的选择是完全摆脱XML和XQuery。只是不确定如何。