用DML
指令操作连接的视图(Join view
)
连接的视图就是:创建该视图时使用的
SELECT
指令中使用到了连接
(join)
查询。而我们使用对
DML(insert ,delete, update)
指令操作连接视图时我们可以使用下列任何条件:
l
分等级的查询从句,如
START WITH
或
CONNECT BY
l
GROUP BY
或
ORDER BY
从句
l
模型查询
l
集合运算,如:
UNION, UNION ALL, INTERSECT, MINUS
l
计算函数,如:
AVG, COUNT, MAX, MIN, SUM,
等
l
分析函数,如:
CUME_DIST
等
l
子查询或者
SELECT
列表中的集合表达式
l
DISTINCT
操作符
l
使用只读选项
l
ROWNUM
虚拟列
DML
指令只能对视中的一个表进行修改,所以视图必须有至少一个表有保护键
键保护的表:
键保护的表是连接的视图可以被修改的最重要的条件,那么什么才是键保护表呢?
我们先看下面两个表定义:
DESC employee
Name Null? Type
----------------------------------------- -------- -------------
EMP_ID NOT NULL NUMBER(5)
FNAME VARCHAR2(20)
LNAME VARCHAR2(20)
DEPT_ID NOT NULL NUMBER(5)
MANAGER_EMP_ID NUMBER(5)
SALARY NUMBER(5)
HIRE_DATE DATE
JOB_ID NUMBER(3)
DESC retailer
Name Null? Type
----------------------------------------- -------- --------------
RTLR_NBR NOT NULL NUMBER(6)
NAME VARCHAR2(45)
ADDRESS VARCHAR2(40)
CITY VARCHAR2(30)
STATE VARCHAR2(2)
ZIP_CODE VARCHAR2(9)
AREA_CODE NUMBER(3)
PHONE_NUMBER NUMBER(7)
SALESPERSON_ID NUMBER(4)
CREDIT_LIMIT NUMBER(9,2)
COMMENTS LONG
定义一个连接视图:
CREATE OR REPLACE VIEW v_rtlr_emp AS
SELECT c.rtlr_nbr, c.name, c.city, e.emp_id,
c.salesperson_id, e.lname sales_rep
FROM retailer c JOIN employee e
ON c.salesperson_id = e.emp_id;
在连接视图
v_rtlr_emp
中有
retailer
表和
employee
表进行连接,那么哪个表才是键保护表呢?在连接视图
v_rtlr_emp
中
c.rtlr_nbr
是唯一的,而
e.emp_id
不是唯一的
(
因为同一个销售员(
salespersion_id
)可以销售给多个零售商(
retailer
)
)
,所以在此视图中,
retailer
表才是键保护表。
你必须记住下面关于键保护表的重要几点:
l
键保护是一个表在一个连接视图中才有的属性,不是表本身的属性。一个表在一个连接视图中也许是一个键保护表,也许它在另一个连接视图中就不一定是一个键保护表。
l
没有必要选择表中带有键(主键,唯一键等)的列到连接视图中以把此表做为键保护表,就像在连接视图
v_rtlr_emp
中,即使我们不选择选
rtlr_nbr
列到视图中,
retailer
表仍然是键保护表。
l
另一方面,即使我们选择了表中带有键(主键,唯一键等)的列到连接视图中,此表也不一定就是键保护表,如,
emp_id
就是一个带有唯一键的列,但是
employee
表却不是键保护列。
l
在连接视图中的表是否是键保护表,不取决于表中的数据,而取决于表定义和表之间的关系。
连接视图的数据是从多个表中取出的,但是任何
DML
指令都只能修改视图中的一个基本表。
下面介绍我们如何使用
INSERT,DELETE UPDATE
指令操作连接视图:
INSERT
指令操作连接视图:
INSERT INTO v_rtlr_emp (rtlr_nbr, name, salesperson_id)
VALUES (345, 'X-MART STORES', 7820);
1 row created.
插入成功,我们再看下面的指令:
INSERT INTO v_rtlr_emp (rtlr_nbr, name, salesperson_id, sales_rep)
VALUES (456, 'LEE PARK RECREATION CENTER', 7599, 'JAMES');
INSERT INTO v_rtlr_emp (rtlr_nbr, name, salesperson_id, sales_rep)
*
ERROR at line 1:
ORA-01776: cannot modify more than one base table through a join view
显然是报错了,原因就是你不能向没有键保护的表进行插入数据。
DELETE
指令操作连接视图:
DELETE FROM v_rtlr_emp
WHERE rtlr_nbr = 214;
1 row deleted.
删除成功,但是视图中有两个表,到底是删除的哪个表呢,答案是删除了键保护的表
retailer
表!
我们看下面一种情况,两个表都是键保护表:
CREATE VIEW v_cust_disputed_ord AS
SELECT d.order_nbr, d.cust_nbr, c.cancelled_dt
FROM disputed_orders d JOIN cust_order c
ON d.order_nbr = c.order_nbr;
View created.
DELETE FROM v_cust_disputed_ord
WHERE order_nbr = 1003;
1 row deleted.
因为这个连接视图的两个表都是键保护表,那么我们到底又是删除的哪个表呢?答非所问案是:当连接视图中有多个键保护表时,删除的是连接中的第一个键保护表。
UPDATE
指令操作连接视图:
看例子:
UPDATE v_rtlr_emp
SET name = 'PRO SPORTS'
WHERE rtlr_nbr = 215;
1 row updated.
更新成功,因为
name
字段是在键保护表(
retailer
表)中
,
再看下面例子:
UPDATE v_rtlr_emp
SET sales_rep = 'ANDREW'
WHERE rtlr_nbr = 214;
SET sales_rep = 'ANDREW'
*
ERROR at line 2:
ORA-01779: cannot modify a column which maps to a non-key-preserved table
报错了,因为
sales_rep
是
employee
中的列,而
employee
不是键保护表。