Необходимо объявить табличную переменную "@TempTable" - PullRequest
0 голосов
/ 28 января 2020

Я хочу добавить скрипт после развертывания для вставки данных. Но когда я выполняю этот скрипт ниже, я получаю сообщение об ошибке:

Должен объявить переменную таблицы "@TempTable".

Цель этого скрипта - принудительно добавить Id, который является первичным ключом, я знаю, что мы можем использовать:

SET IDENTITY_INSERT [dbo].[TableName] ON;
GO

и после слияния

SET IDENTITY_INSERT [dbo].[TableName] OFF;
GO

Но это не работает для меня, я не могу развернуть свой DacPa c

DECLARE @vehicleType TABLE(
    [VehicleTypeId] BIGINT, 
    [Name] NVARCHAR(200) NOT NULL
);



INSERT INTO @VehicleType ([VehicleTypeId], [Name]) 
VALUES(1,'Automobile'),(2,'HeavyVehicle'),(3,'Motorcycle')

SET IDENTITY_INSERT [dbo].[VehicleType] ON;
GO

MERGE INTO [dbo].[VehicleType]
    USING  @VehicleType as vhlt
        ON ([dbo].[VehicleType].[VehicleTypeId] = vhtl.[VehicleTypeId] and [dbo].[VehicleType].[Name] = vhlt.[Name])
        WHEN NOT MATCHED THEN 
            INSERT VALUES ([VehicleTypeId], [Name]);

SET IDENTITY_INSERT [dbo].[VehicleType] OFF;
GO

1 Ответ

0 голосов
/ 28 января 2020

Первое, на что мне нужно обратить внимание, это то, что таблица поиска, подобная этой, должна , а не иметь столбец с автоматическим номером (IDENTITY). Значения автонумерации syntheti c и должны использоваться только тогда, когда вам все равно , что это за значение, только то, что оно уникально. Это хорошо работает, когда пользователи могут добавлять значения в набор поиска.

Для таблиц поиска, не обслуживаемых пользователем, таких как VehicleType, вам do все равно, какие значения VehicleTypeId так что авто-номер работает против вас. Если вы можете удалить свойство IDENTITY из определения столбца, вам абсолютно необходимо. Если вы не можете, вы застряли, используя IDENTITY_INSERT. Только не забудьте использовать IDENTITY в будущих конструкциях справочных таблиц.


Есть способ сделать это без табличной переменной: используйте CTE с оператором MERGE.

CTE будет содержать все значения, которые вы хотите использовать, используя объединенные операторы stati c SELECT (использование UNION ALL пропускает повторные проверки, поскольку вы знаете, что дубликатов не будет). Оператор MERGE использует CTE в качестве исходной таблицы.

Предложение ON в операторе MERGE должно сравнивать только первичный ключ. Если значение в неключевом столбце было изменено, это приведет к вставке новой строки; новый ряд будет нарушать первичный ключ. Вместо этого обновите столбец Name до значения в CTE. Для этого я добавил ниже предложение WHEN MATCHED.

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

Мне нравится называть CTE src, поэтому мне не нужно его псевдонимом.

-- Only IF you cannot remove the IDENTITY property from VehicleTypeId:
SET IDENTITY_INSERT [dbo].[VehicleType] ON;
GO

-- Stage the data and merge it into the table in one shot:
WITH [src] ([VehicleTypeId], [Name])
AS
(
    SELECT           1, 'Automobile'
    UNION ALL SELECT 2, 'HeavyVehicle'
    UNION ALL SELECT 3, 'Motorcycle'
)
MERGE INTO [dbo].[VehicleType] AS [dst]
USING [src]
    ON [dst].[VehicleTypeId] = src.[VehicleTypeId]
WHEN NOT MATCHED BY TARGET THEN
    INSERT ([VehicleTypeId], [Name])
    VALUES ([src].[VehicleTypeId], [src].[Name])
WHEN MATCHED AND ([dst].[Name] <> [src].[Name]) THEN
    UPDATE
    SET [Name] = [src].[Name]
;
GO

-- Again, only IF you cannot remove the IDENTITY property from VehicleTypeId:
SET IDENTITY_INSERT [dbo].[VehicleType] OFF;
GO

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

...
OUTPUT $action AS [*Action],
    COALESCE([inserted].[VehicleTypeId], [deleted].[VehicleTypeId]) AS [=VehicleTypeId],
    [deleted].[Name] AS [-Name],
    [inserted].[Name] AS [+Name]
    -- Repeat deleted and inserted AS -/+ for remaining non-key columns.
;

Примечание о префиксах, которые я Вы использовали псевдонимы:

  • * для столбцов метаданных (на самом деле, это только когда-либо *Action).
  • = для столбцов первичного ключа. Они не изменятся, поэтому только один на столбец в ключе.
  • - для старых значений (например, -Name).
  • + для новых значений (например, +Name).
...