0

我有一个可更新的视图,它使用一个代替触发器来进行插入/更新。该触发器使用合并。我发现 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 触发器中的默认值中有类似的东西,并通过将插入的行复制到临时表中然后更改临时表以添加物理表中的默认约束来解决它。我不确定我能否容忍这些额外步骤的性能问题。

4

1 回答 1

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

)

您会看到 surname 的默认值开始出现。不幸的是,这对您尝试做的事情并没有太大帮助。我能想到的最好的解决方案(而且不是很好)是使用 isnulls 将默认值放入触发器中。

When Not Matched By Target Then
Insert
(
    id,
    forename,
    surname

)
Values
(
    ISNULL(i.id,newid()),
    i.forename,
    ISNULL(i.surname,'xxyyzz')

)

我意识到从维护的角度来看这不是很好,但它会起作用。如果您有兴趣,我在此处发布了关于 DEFAULT 关键字的帖子,其中包含相当多的详细信息。

于 2013-03-17T03:53:06.897 回答