oracle 每日一题-可修改的视图

来源:互联网 发布:中文域名证书生成器 编辑:程序博客网 时间:2024/05/20 06:51

原始出处:
http://www.plsqlchallenge.com/

作者:        ChrisSaxon

运行环境:SQLPLUS, SERVEROUTPUT已打开

你正在创建一个应用来管理员工的项目。它会在如下的模式存储详细信息:

create table plch_departments (
  department_id   int not null primary key,
  department_name varchar2(100) not null
);

create table plch_employees (
  employee_id   int not null primary key,
  employee_name varchar2(100) not null,
  department_id int not null 
    references plch_departments ( department_id )
);

create table plch_employee_projects (
  employee_id int not null 
    references plch_employees ( employee_id ),
  project_id int not null,
  primary key ( employee_id, project_id )
);

insert into plch_departments values (1, 'Major department');

commit;


下列的哪些选项:
创建了视图 plch_employees_v
使得下列的插入语句执行不出错?

insert into plch_employees_v (
  employee_id, employee_name, department_id
) values (
  1, 'Chris', 1
);

(A) 
create or replace view plch_employees_v as 
  select emp.employee_id, emp.employee_name, emp.department_id  
  from   plch_employees emp;

(B) 
create or replace view plch_employees_v as 
  select emp.employee_id, emp.employee_name, emp.department_id  
  from   plch_employees emp
  join   plch_departments dep
  on     emp.department_id = dep.department_id;

(C) 
create or replace view plch_employees_v as 
  select emp.employee_id, emp.employee_name, emp.department_id, 
         dep.department_name
  from   plch_employees emp
  join   plch_departments dep
  on     emp.department_id = dep.department_id;

(D) 
create or replace view plch_employees_v as 
  select emp.employee_id, emp.employee_name, emp.department_id 
  from   plch_employees emp
  join   plch_employee_projects epr
  on     emp.employee_id = epr.employee_id;

(E) 
create or replace view plch_employees_v as 
  select emp.employee_id, emp.employee_name, emp.department_id,
         epr.project_id
  from   plch_employees emp
  join   plch_employee_projects epr
  on     emp.employee_id = epr.employee_id;

create or replace trigger plch_emp_iit
instead of insert on plch_employees_v
begin
  insert into plch_employees (
    employee_id, employee_name, department_id
  ) values (
    :new.employee_id, :new.employee_name, :new.department_id
  );
end;
/


A:(推荐)

这选项只选择了来自plch_employees的列。所以这个视图是“保键”的("key preserved")。查询没有函数或操作符,所以你能够插入数据。
B: Plch_employees是plch_departments的子表。连接发生在plch_employees的主键。所以它是保键的。这意味着来自plch_employees的每一行数据在视图中最多出现一次。所以你可以往表中插入数据。
C: 如同前一选项,plch_employees仍然是保键的。往视图中加上来自plch_departments的列也不会改变这一点。所以你仍然可以用这个视图向plch_employees插入数据。
D: Plch_employee_projects是plch_employees的子表。连接上它就意味着当你查询视图的时候,一个employee的行可能出现多次。所以plch_employees不再是保键的。因此你在执行INSERT的时候会得到这个错误:
"ORA-01779: cannot modify a column which maps to a non key-preserved table" 

E: instead of触发器会拦截视图上的DML操作。所以ORACLE在视图中执行语句而不是在基表上执行。这解决了plch_employees的保键问题,插入可以成功执行。



这题做的有点累:首先去找保键:


没法子,去找instead of insert 触发器,结果找了一波08年10年的资料,上面说instead of 可以和替换的一起发生,并且可以写在表上,近几年更新,是替换而且只发生在视图上。

琢磨这句话E: instead of触发器会拦截视图上的DML操作。所以ORACLE在视图中执行语句而不是在基表上执行。这解决了plch_employees的保键问题,插入可以成功执行。

应该表述错了:instead of触发器会拦截视图上的DML操作。所以ORACLE在基表中执行语句而不是在视图上执行。这解决了plch_employees的保键问题(没有视图的事了),插入可以成功执行(插入到plch_employees,视图里没有)。

01779是这样的:


关键是一句话:一个数据只能出现一行(一次)。


0 0