Вместо триггера при просмотре с использованием слияния не применяются значения таблицы по умолчанию
У меня есть обновляемое представление, использующее вместо триггера для вставки / обновления. Этот триггер использует Merge. Я обнаружил, что оператор Merge не применяет ограничения по умолчанию из базовой физической таблицы, хотя в документации по слиянию это рекомендуется.
Следующий пример демонстрирует:
create table tblTest
(
id uniqueidentifier not null primary key default newid(),
forename varchar(20),
surname varchar(20) not null default 'xxyyzz'
)
go
create view vwTest as select * from tblTest
go
create Trigger vwTest_trigger_insteadof_insert_update On vwTest
Instead of Insert, Update As
begin
set nocount on
Merge tblTest t
Using
inserted i On (t.id = i.id)
When Matched Then
Update
Set
t.forename = i.forename,
t.surname = i.surname
When Not Matched By Target Then
Insert
(
id,
forename,
surname
)
Values
(
i.id,
i.forename,
i.surname
)
OUTPUT $action, Inserted.*, Deleted.*
;
end
go
--Inserts to physical table work as expected
insert into tblTest (id) values (newid())
insert into tblTest (surname) values ('smith')
--Inserts into updateable view fail as no defaults are set
--from the underlying physical table
insert into vwTest (id) values (newid())
insert into vwTest (surname) values ('jones')
Я вижу, что у кого-то было что-то похожее в разделе Использование значений по умолчанию в триггере INSTEAD OF INSERT, и он решил эту проблему, скопировав строки, вставленные во временную, а затем изменив временную таблицу, добавив ограничения по умолчанию из физической таблицы. Я не уверен, что мог бы терпеть проблемы с производительностью этих дополнительных шагов.
1 ответ
Достаточно просто. Чтобы использовать значение по умолчанию, нужно либо использовать ключевое слово DEFAULT, либо не включать его в вставку. Даже значение NULL считается. В этом случае вы указываете значение в вставке в вашем триггере. Если бы вы изменили эту часть от
When Not Matched By Target Then
Insert
(
id,
forename,
surname
)
Values
(
i.id,
i.forename,
i.surname
)
в
When Not Matched By Target Then
Insert
(
id,
forename,
surname
)
Values
(
i.id,
i.forename,
DEFAULT
)
Вы бы увидели значение по умолчанию для начала фамилии. К сожалению, это не очень помогает вам в том, что вы пытаетесь сделать. Лучшее решение, которое я могу придумать (и оно не очень хорошее), - это ввести значения по умолчанию в триггер с помощью isnulls.
When Not Matched By Target Then
Insert
(
id,
forename,
surname
)
Values
(
ISNULL(i.id,newid()),
i.forename,
ISNULL(i.surname,'xxyyzz')
)
Я понимаю, что это не очень хорошо с точки зрения обслуживания, но это будет работать. Я сделал пост по ключевому слову DEFAULT здесь с достаточным количеством деталей, если вам интересно.