6.2 视图的DML操作
针对简单视图可以进行DML操作,而针对复杂视图不可以进行DML操作。之前创建emp_hidedata_view是一个简单视图,接下来尝试对这个视图进行删除、更新和插入操作。
- 删除简单视图行
执行下面针对视图emp_hidedata_view的删除语句,并提交事务,经确认,雇员表中编号为208的记录(确定之前插入了该记录)被删除,说明针对简单视图的删除操作对视图的基表起了作用。
DELETE FROM emp_hidedata_view WHERE "id" = 208
- 更新简单视图行
执行下面针对视图emp_hidedata_view的更新语句,并提交事务,经确认,雇员表中编号为207的雇员(确定之前插入了该记录),其姓氏从“Wang”变成了“Wan”,如图6.7所示。这说明针对简单视图的更新操作也对视图的基表起了作用。
UPDATE emp_hidedata_view
SET "Name" = 'Wan'
WHERE "id" = 207
图6.7 更新简单视图行
- 插入简单视图行
执行下面针对视图emp_hidedata_view的插入语句,Oracle提示无法将NULL插入雇员表的EMAIL字段,插入简单视图行不成功。
INSERT INTO emp_hidedata_view
VALUES(210,'Jiang','17-6月-13')
插入不成功的原因在于,在创建emp_hidedata_view视图时,选择了雇员表employees的雇员编号、姓氏和雇佣日期,并没有选择EMAIL等其他字段。这些没有选择的字段在雇员表employees中有非空字段,而当向emp_hidedata_view视图插入行时,最终是要给雇员表employees插入行,但实际插入的数据不包括这些非空字段的值,所以插入时出错。
假设针对部门表departments创建下面的视图dept_hidedata_view,包括部门表中的部门编号和部门名称两个非空字段,不包括经理编号和所在地编号两个可以为空的字段,其SQL语句如下:
CREATE OR REPLACE VIEW dept_hidedata_view
AS SELECT department_id, department_name FROM departments
针对这个简单视图dept_hidedata_view插入行,SQL语句如下,提交事务,经确认,部门表中已经插入了编号为310的部门信息。
INSERT INTO dept_hidedata_view
VALUES(310,'Department3')
- DML操作规则
可以通过视图对基表进行DML操作,但针对不同的操作,需要符合下面的规则。如果视图中包含下面的内容,就不可以从视图中删除数据:
(1)组函数。
(2)GROUP BY子句。
(3)DISTINCT关键字。
(4)伪列ROWNUM关键字。
如果视图中包含下面的内容,就不可以在视图中更新数据:
(1)组函数。
(2)GROUP BY子句。
(3)DISTINCT关键字。
(4)伪列ROWNUM关键字。
(5)用表达式定义的字段。
如果视图中包含下面的内容,就不可以在视图中插入数据:
(1)组函数。
(2)GROUP BY子句。
(3)DISTINCT关键字。
(4)伪列ROWNUM关键字。
(5)用表达式定义的字段。
(6)基表中的NOT NULL字段不在视图中。
- WITH CHECK OPTION和WITH READ ONLY
WITH CHECK OPTION子句指出,通过视图执行的插入和更新的操作,不能产生视图不能选择的行。该子句是在数据插入或更新时进行完整性约束和数据验证检查,WITH CHECK OPTION子句后面可以跟约束名。
例如针对雇员表employees创建了如下的视图,要求部门编号必须为60,其SQL语句如下:
CREATE OR REPLACE VIEW emp_dept60_view
AS SELECT * FROM employees WHERE department_id = 60
WITH CHECK OPTION CONSTRAINT emp_dept60_ck
针对该视图执行如下的更新操作,将会显示错误,提示“视图WITH CHECK OPTION WHERE子句违规”。
UPDATE emp_dept60_view
SET department_id = 310
WHERE employee_id = 207
其原因在于,创建视图时WHERE子句中要求部门编号为60的数据才会被选中。而通过UPDATE更新视图后,将部门编号更改为非60,即产生了视图不能通过WHERE子句选择的行,所以提示错误。
WITH READ ONLY比较简单,通过添加WITH READ ONLY选项,能够确保无DML操作发生。