视图
视图DML操作
注意:只能基于一个表的视图才能进行DML操作,对视图的DML操作实际上是对单表的操作
获取用户的所有表名或视图名
视图插入数据:
没有插入主键sno定义的值
查看原因:基表的sno是主键
修改视图
插入数据
查看视图
在原表的数据
with check option:要注意插入的数据要满足约束条件
with read only:只读,不能插入数据
修改和删除数据与插入数据一样,参照插入数据
是否可以要看具体情况,不能一概而论。
下面是一些说明:
视图提供了从一个表或多个表查看数据的方式。
视图实际上是一个对结果数据集的命名。它是一个SELECT语句,只要视图被引用,它就会执行。因此,视图可以被认为和物理基础表(base table)一样拥有列和行。对于取出数据,视图可以像其他基础表一样被使用。视图是否可以被执行insert、update、delete操作,取决于它的定义。
在Oracle中,当你创建的视图来源于多个基础表或视图时,这样的视图叫做连接视图Join Views。
例如如下语句创建的视图就是Join View。
CREATE VIEW division1_staff AS
SELECT ename, empno, job, dname
FROM emp, dept
WHERE emp.deptno IN (10, 30)
AND emp.deptno = dept.deptno;
如果一个join view允许进行UPDATE、 INSERT和DELETE操作,这样的视图叫做可更新的连接视图updatable join view。
updatable join view是在最外层select语句的from子句中包括一个以上的表,并且没有用WITH READ ONLY 子句进行限制。
updatable join views的规则如下:
规则
描述
通用规则
任何对join view的INSERT、UPDATE或DELETE操作,一次只能修改一个基础表
UPDATE规则
join view中所有被修改的列,必须可以对应到一个key-preserved table中的列。 如果视图定义的时候使用了WITH CHECK OPTION子句,则所有连接的列和重复出现的表中的列都是不可修改的。
DELETE 规则
当join view有且只有一个key-preserved table时,才可以被删除操作。如果视图定义使用了WITH CHECK OPTION子句,并且key preserved table重复出现,则视图中的数据行是不能被删除的。
INSERT 规则
INSERT语句不能显式或隐式的涉及nonkey preserved table中的列。 如果join view定义时使用了WITH CHECK OPTION子句,则INSERT操作是不允许的。
key-preserved table: 表中每一个key同时也是join的结果集的key,那么这个表叫做key-preserved,因为他的Keys通过join后被保留下来了。
key-preserving的特性不是根据视图的实际结果数据决定的,而是由视图和基础表的物理结构决定的。
以上描述的是视图被创建的时候具有的inherently modifiable特性。对于复杂的view,如果不能用DML语句(insert、update、delete)直接更改,还可以用INSTEAD OF triggers进行显式的更改。这些triggers叫做INSTEAD OF triggers,因为不像其他类型的triggers,Oracle执行trigger来代替执行出发trigger的语句。这些trigger必须定义如何直接对基础表进行UPDATE、INSERT 或 DELETE操作。
你可以正常的对视图进行UPDATE、INSERT和DELETE操作,INSTEAD OF trigger会在后台运行,保证对基础表的正确处理。INSTEAD OF triggers只能定义为每一行触发。
由此可见,对于视图的更新机制,在不同的数据库中有很大的不同。我们在数据库设计的时候,可以根据不同的数据库灵活的使用视图,但是相伴而来的一个问题就是在系统在不同数据库之间进行移植的时候会增大工作量。
/*
drop table a
drop table b
go
*/
create table A(ID int identity(1,1) primary key,Avalue varchar(10))
create table B(ID int identity(1,1) primary key,AID int,Bvalue varchar(10))
go
/*
drop view AB_view
go
*/
create view AB_view
as
select A.*, B.Bvalue from A join B on (A.ID = B.AID)
go
--drop trigger AB_tr on AB_view
create trigger AB_tr on AB_view instead of insert
as
begin
insert into a(Avalue)
select Avalue
from
(
select distinct id,Avalue
from inserted i
)t
insert into b(aid,Bvalue)
select scope_identity(),Bvalue
from inserted i
end
go
insert into AB_view (Avalue, Bvalue) values ('A3', 'B3')
select * from a
/*
IDAvalue
1A3
*/
select * from b
/*
IDAIDBvalue
11B3
*/
/*
--建立2个表
create table t1(id int not null primary key,tbl varchar(5) not null)
create table t2(id int not null primary key,tbl varchar(5) not null)
go
--插入数据
insert into t1
select object_id,'01'
from sys.objects
insert into t2
select OBJECT_ID ,'02'
from sys.objects
if exists(select * from sys.views where name = 'v_t')
drop view v_t
go
--创建视图
create view v_t
as
select * from t1
union all
select * from t2
go
*/
if exists(select * from sys.triggers where name = 'trigger_t')
drop trigger dbo.trigger_t
go
--1.通过判断区分列tbl的值是'01'或'02',把数据分别插入t1或t2
create trigger dbo.trigger_t
on dbo.v_t
instead of insert
as
declare @t varchar(8);
set @t = '';
if @t = '01'
insert into dbo.t1
select * from inserted
else
insert into dbo.t2
select * from inserted
go
--1.测试
insert into v_t
select 115,'02'
select *
from dbo.t2
where ID = 115
if exists(select * from sys.triggers where name = 'trigger_t')
drop trigger dbo.trigger_t
go
--2.通过判断区分列tbl的值是'01'或'02',来动态生成语句实现插入数据
create trigger dbo.trigger_t
on dbo.v_t
instead of insert
as
declare @t varchar(8);
declare @sql varchar(max);
declare @id int ;
set @t = '';
select @t = tbl,@id = ID
from inserted
set @sql = 'insert into dbo.t' + RIGHT(@t,1) +
'(id,tbl) values(' +
+ CAST(@id as varchar) + ',''' + @t +''')'
exec(@sql)
go
--2.测试
insert into v_t
select 116,'01'
select *
from dbo.t1
where ID = 116
if exists(select * from sys.triggers where name = 'trigger_t')
drop trigger dbo.trigger_t
go
--3.前两种是通过insted of触发器来实现的,接下来通过check约束来实现
--先删除原来的主键,因为分区列必须包含在主键中
alter table t1
drop constraint PK__t1__3213E83F7F60ED59
--可以不加check约束,但会导致查询优化器必须要搜索所有的表
--加了check约束后,会直接搜索符合分区依据列的表.
alter table t1
add constraint ck_t1_tbl check(tbl='01')
--加上主键约束
alter table t1
add constraint pk_t1 primary key(id,tbl)
alter table t2
drop constraint PK__t2__3213E83F03317E3D
alter table t2
add constraint ck_t2_tbl check(tbl='02')
alter table t2
add constraint pk_t2 primary key(id,tbl)
--3.测试
insert into v_t
select 12345,'01'
select *
from dbo.t1
where ID = 12345
--4.建立索引视图
if exists(select * from sys.views where name = 'v_t')
drop view v_t
go
--创建视图
--必须加上架构,以及明确指定列
create view dbo.v_t
with schemabinding
as
select ID,tbl from dbo.t1
union all
select id,tbl from dbo.t2
go
select * from v_t
/*
报错:
消息 10116,级别 16,状态 1,第 1 行
无法对视图 'WC.dbo.v_t' 创建 索引,
因为其中包含一个或多个 UNION、INTERSECT 或 EXCEPT 运算符。
如果将查询作为原始视图的 UNION、INTERSECT 或 EXCEPT 运算符的输入,
请考虑为每个这样的查询创建一个单独的索引视图。
说明当视图中有union all时,无法建立索引视图
*/
create unique clustered index idx_v_t on dbo.v_t(id)
视图
视图DML操作
注意:只能基于一个表的视图才能进行DML操作,对视图的DML操作实际上是对单表的操作获取用户的所有表名或视图名
视图插入数据:
没有插入主键sno定义的值
查看原因:基表的sno是主键修改视图
插入数据
查看视图
在原表的数据with check option:要注意插入的数据要满足约束条件
with read only:只读,不能插入数据
修改和删除数据与插入数据一样,参照插入数据
转载于:https://www.cnblogs.com/feiZhou/p/9344388.html
今天在使用视图时偶然间发现不能向视图中插入数据,后经过排查找到了原因,特此记录下来。下面请看简单的视图demo ,如下所示,
- CREATE OR REPLACE VIEW t5
- AS
- SELECT last_name ,email
- FROM employees ;
-
- SELECT * FROM t5;
就是这样一个很简单的视图,当我使用插入语句时,发现一直无法插入, 插入语句如下所示:
INSERT INTO t5 VALUES('张飞','zf@163.com');
异常信息如下所示:

造成该问题的原因是: 当向视图中插入数据时,同时也会向原表插入数据插入数据 ,而原表(employees)中存在多个字段不允许为空,所以无法插入 ,将这些不允许为空的字段修改为允许为空即可。