Альтернатива XML в SQL? PIVOT может быть? - PullRequest
0 голосов
/ 20 марта 2019

В настоящее время мы используем OUTPUT для INSERT и UPDATE в хранимых процедурах, чтобы объединить строку для преобразования в XML для отслеживания того, что было изменено. Затем этот XML помещается в UDT и передается другой процедуре, где он анализируется и помещается в физическую таблицу отслеживания.

Мы отслеживаем имя таблицы, значение PK строки изменилось, столбец изменился, старые и новые значения, идентификатор пакета для определения значений, измененных одновременно, а также кто / когда измененное.

Процедура синтаксического анализа XML с целью его включения в фактическую таблицу отслеживания является существенным узким местом производительности. Я пытаюсь придумать альтернативы этому, но у меня мало шансов. Единственное, о чем я могу думать, это, возможно, какой-то PIVOT в запросе OUTPUT, чтобы поместить значения в UDT в их исходной форме, а не в конкатенацию в XML.

Это образец оператора 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)

Proc делает немного больше вещей перед тем, как вставлять в таблицу отслеживания. Однако XQuery составляет 99,9% - 100% от плана выполнения. В идеале, я думаю, лучше всего было бы полностью избавиться от XML и XQuery. Просто не знаю как.

...