插入到SQL SERVER中的多表视图中

SHR*_*SHR 4 sql-server view

我问这个问题的方式是尝试了解我遇到的类似情况,并尝试了解插入视图是如何工作的。

我有这些表:

Create table A([id] int primary key not null, value nvarchar(50) NULL)
Create table B([id] int primary key not null, value nvarchar(50) NULL)
Run Code Online (Sandbox Code Playgroud)

我从两个表创建视图,如下所示:

create View V as (select * from A) UNION ALL (select * from B)
Run Code Online (Sandbox Code Playgroud)

我在 V 视图上有这个触发器:

Create trigger v_trig on V instead of insert AS
  insert into v (id,value) select id,value from inserted
Run Code Online (Sandbox Code Playgroud)

当我尝试插入到我的视图中时,出现以下错误:

消息 4436,级别 16,状态 12,过程 v_trig,第 2 行

UNION ALL 视图“db.dbo.V”不可更新,因为未找到分区列

我有一个具有类似视图(带有union all)的数据库,出于某种原因,我可以毫无问题地插入它,我试图理解为什么。

我应该怎么做才能允许插入到诸如视图之类的视图中?有没有办法以插入的方式决定(不更改触发器)哪个是视图的默认表?

EzL*_*zLo 5

您只能在插入分区视图时执行此操作(触发器无关) ,该视图可以存储基础表具有与 a不相交的适当约束UNION ALL的数据,因此 an会明确地进入一个基础表。CHECKprimary keyINSERT


按照您的示例,如果您限制 table 的某些值A、 table 的其他值B并添加复合主键:

Create table A(
    [id] int, 
    value nvarchar(50), 
    CHECK (value = 'A'),
    PRIMARY KEY (ID, value))

Create table B(
    [id] int, 
    value nvarchar(50), 
    CHECK (value = 'B'),
    PRIMARY KEY (ID, value))
Run Code Online (Sandbox Code Playgroud)

视图保持不变:

create View V as (select id, value from A) UNION ALL (select id, value from B)
Run Code Online (Sandbox Code Playgroud)

现在您可以成功地直接插入到视图中(不需要触发器):

insert into v (id, value) select 1,'B' 
-- (1 row(s) affected)
Run Code Online (Sandbox Code Playgroud)

有没有办法以插入的方式决定(不更改触发器)哪个是视图的默认表?

插入 with 与for 表(分区列)value = 'B'匹配,因此该行会自动按此方式插入。由于检查列必须是主键的一部分,因此 SQL 引擎知道该行属于该表而不属于任何其他表,因为它们都具有具有相同列和不同检查值的主键。您无法手动控制它。CHECKB

如果您尝试插入任何约束都不支持的值CHECK...

insert into v (id, value) select 1,'C' 
--Msg 4457, Level 16, State 1, Line 1
--The attempted insert or update of the partitioned view failed because the value of the partitioning column does not belong to any of the partitions.
--The statement has been terminated.
Run Code Online (Sandbox Code Playgroud)

检查视图插入起作用的表的 DDL,您将看到不相交的CHECK约束。