Как обрабатывать выходные значения, не включенные в SQL-вставку - PullRequest
0 голосов
/ 29 октября 2019

Я пишу процесс импорта, который будет импортировать данные из одной (несколько устаревшей) базы данных в другую. Процесс импорта занимает одну плоскую таблицу с исходными данными. У меня есть это заполнение временной таблицы (#SourcePersonAccount) в начале. Цель состоит в том, чтобы распределить эти данные в три таблицы назначения (dbo.Person, dbo.Account & dbo.PersonAccount). Это выполняется в триггере для таблицы, использующей репликацию SQL Server, поэтому должен выполняться быстро.

#SourcePersonAccount([AccountNumber], [CompanyId], [TargetPersonId], [TargetAccountId]);
dbo.Person ([Id] pk identity(1,1), [CompanyId], ...);
dbo.Account ([Id] pk identity(1,1), [AccountNumber], ...);
dbo.PersonAccount ([Id], [PersonId] fk_Person_Id, [AccountId] fk_Account_Id);

В моем коде у меня есть TargetPersonId, уже заполненный во временной таблице #SourcePersonAccount. Осталось только: 1) вставить в dbo.Account, 2) обновить #SourcePersonAccount с добавленным значением dbo.Account.Id, 3) вставить в dbo.PersonAccount.

Одна из проблем заключается в том, что AccountNumber и CompanyId составляют составной первичный ключ исходной таблицы, поэтому они необходимы для правильного соединения с временной таблицей #SourcePersonAccount.

Я видел потоки, в определенной степени решающие подобные проблемы здесь и здесь , которые не решили мою конкретную проблему, в основном из-за проблем с производительностью.

Как указано в в этом посте , предложение OUTPUTне может выводить столбцы, которые не были включены во вставку, так что это не вариант здесь.

Одно решение, которое я видел, технически может дать желаемый результат (я не могу найти ссылку на то, где я нашел предложение) при использовании предложения OUTPUT фактически добавляется и удаляется столбец в запросе.

DECLARE @PersonAccountTbl TABLE ([AccountId] INT, [AccountNumber] INT, [CompanyId] INT);

ALTER TABLE [dbo].[Account]
    ADD [CompanyId] INT NULL;

INSERT INTO [dbo].[Account]
    ([AccountNumber], [CompanyId])
OUTPUT INSERTED.[Id], INSERTED.[AccountNumber], INSERTED.[CompanyId]
INTO @PersonAccountTbl
SELECT
    [AccountNumber], [CompanyId]
FROM #SourcePersonAccount
WHERE
    [TargetAccountId] IS NULL;

ALTER TABLE [dbo].[Account]
    DROP COLUMN [CompanyId];

Это недопустимый вариант для моей ситуации.

Я пытался использовать MERGE как и все темы, которые я нашел в этом выпускеМы рекомендуем использовать его. Мне не нравится MERGE по по нескольким причинам . Я все равно попробовал;приведенный ниже код дает желаемый результат, но в конечном итоге он оказался слишком медленным для моих целей.

DECLARE @PersonAccountTbl TABLE ([AccountId] INT, [AccountNumber] INT, [CompanyId] INT);

MERGE INTO [dbo].[Account] a
USING #SourcePersonAccount spa
    ON spa.[TargetAccountId] IS NULL
WHEN NOT MATCHED THEN
    INSERT
        ([AccountNumber])
    VALUES
        (spa.[AccountNumber])
    OUTPUT INSERTED.[Id], INSERTED.[AccountNumber], spa.[CompanyId]
    INTO @PersonAccountTbl ([AccountId], [AccountNumber], [CompanyId]);

UPDATE spa
    SET spa.[TargetAccountId] = pat.[AccountId]
FROM #SourcePersonAccount spa
JOIN @PersonAccountTbl pat
    ON pat.[AccountNumber] = spa.[AccountNumber]
    AND pat.[CompanyId] = spa.[CompanyId];

INSERT INTO [dbo].[PersonAccount]
    ([PersonId], [AccountId])
SELECT
    spa.[TargetPersonId], spa.[TargetAccountId]
FROM #SourcePersonAccount spa
LEFT JOIN [dbo].[PersonAccount] pa
    ON pa.[PersonId] = spa.[TargetPersonId]
    AND pa.[AccountId] = spa.[TargetAccountId]
WHERE
    pa.[Id] IS NULL;

Есть ли способ , отличный от MERGE или добавление / удаление столбца длявыполнить это?

1 Ответ

1 голос
/ 29 октября 2019

Вы можете использовать SEQUENCE вместо столбца IDENTITY. Затем вы можете назначить идентификаторы временной таблице или табличной переменной, прежде чем вставлять данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...