Я использую SQL Server 2016 и пытаюсь создать оператор MERGE
, который будет вставлять новую запись, если она не существует, или получать идентификатор записи, если она существует.
Это работает правильно, но имеет непреднамеренный побочный эффект, вызывающий обновление индексированного представления, даже если данные не обновляются, когда я запускаю это несколько раз.
Это ожидаемое поведение или я просто делаю что-то не так?
Интуитивно я предполагаю, что ожидал, что, поскольку слияние находит совпадение, затем обновляет только локальную переменную, никаких изменений в индексированной вид вообще будет отображаться в плане выполнения.
CREATE TABLE dbo.Customer
(
CustomerId INT IDENTITY(100,1) PRIMARY KEY NOT NULL,
CustomerName VARCHAR(100) NOT NULL
)
GO
CREATE VIEW dbo.Customer_v
WITH SCHEMABINDING
AS
SELECT CustomerId, CustomerName
FROM dbo.Customer
GO
CREATE UNIQUE CLUSTERED INDEX [CL_IX_Customer_v]
ON dbo.Customer_v(CustomerId ASC);
GO
DECLARE @CustomerId AS INT
DECLARE @CustomerName AS VARCHAR(100) = 'Mike Smith'
DECLARE @WasCustomerCreated AS BIT = 0
DECLARE @SummaryOfChanges TABLE(Change VARCHAR(20));
MERGE INTO dbo.Customer AS Target
USING (VALUES (@CustomerName)) AS Source (CustomerName) ON (Target.CustomerName = Source.CustomerName)
WHEN MATCHED THEN
UPDATE SET @CustomerId = Target.CustomerId
WHEN NOT MATCHED THEN
INSERT (CustomerName) VALUES (@CustomerName)
OUTPUT $action INTO @SummaryOfChanges;
IF EXISTS(SELECT * FROM @SummaryOfChanges WHERE Change = 'Insert')
BEGIN
SET @WasCustomerCreated = 1
SET @CustomerId = SCOPE_IDENTITY()
END
SELECT @CustomerId AS CustomerId, @WasCustomerCreated AS WasCustomerCreated