6.2 视图的DML操作

  针对简单视图可以进行DML操作,而针对复杂视图不可以进行DML操作。之前创建emp_hidedata_view是一个简单视图,接下来尝试对这个视图进行删除、更新和插入操作。

  • 删除简单视图行

  执行下面针对视图emp_hidedata_view的删除语句,并提交事务,经确认,雇员表中编号为208的记录(确定之前插入了该记录)被删除,说明针对简单视图的删除操作对视图的基表起了作用。

  1. DELETE FROM emp_hidedata_view WHERE "id" = 208
  • 更新简单视图行

  执行下面针对视图emp_hidedata_view的更新语句,并提交事务,经确认,雇员表中编号为207的雇员(确定之前插入了该记录),其姓氏从“Wang”变成了“Wan”,如图6.7所示。这说明针对简单视图的更新操作也对视图的基表起了作用。

  1. UPDATE emp_hidedata_view
  2. SET "Name" = 'Wan'
  3. WHERE "id" = 207

6.2 视图的DML操作 - 图1


图6.7 更新简单视图行

  • 插入简单视图行

  执行下面针对视图emp_hidedata_view的插入语句,Oracle提示无法将NULL插入雇员表的EMAIL字段,插入简单视图行不成功。

  1. INSERT INTO emp_hidedata_view
  2. VALUES(210,'Jiang','17-6月-13')

  插入不成功的原因在于,在创建emp_hidedata_view视图时,选择了雇员表employees的雇员编号、姓氏和雇佣日期,并没有选择EMAIL等其他字段。这些没有选择的字段在雇员表employees中有非空字段,而当向emp_hidedata_view视图插入行时,最终是要给雇员表employees插入行,但实际插入的数据不包括这些非空字段的值,所以插入时出错。

  假设针对部门表departments创建下面的视图dept_hidedata_view,包括部门表中的部门编号和部门名称两个非空字段,不包括经理编号和所在地编号两个可以为空的字段,其SQL语句如下:

  1. CREATE OR REPLACE VIEW dept_hidedata_view
  2. AS SELECT department_id, department_name FROM departments

  针对这个简单视图dept_hidedata_view插入行,SQL语句如下,提交事务,经确认,部门表中已经插入了编号为310的部门信息。

  1. INSERT INTO dept_hidedata_view
  2. 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语句如下:

  1. CREATE OR REPLACE VIEW emp_dept60_view
  2. AS SELECT * FROM employees WHERE department_id = 60
  3. WITH CHECK OPTION CONSTRAINT emp_dept60_ck

  针对该视图执行如下的更新操作,将会显示错误,提示“视图WITH CHECK OPTION WHERE子句违规”。

  1. UPDATE emp_dept60_view
  2. SET department_id = 310
  3. WHERE employee_id = 207

  其原因在于,创建视图时WHERE子句中要求部门编号为60的数据才会被选中。而通过UPDATE更新视图后,将部门编号更改为非60,即产生了视图不能通过WHERE子句选择的行,所以提示错误。

  WITH READ ONLY比较简单,通过添加WITH READ ONLY选项,能够确保无DML操作发生。