用数据字典视图获得可更新的列

 

Oracle 提供了一种数据字典视图 USER_UPDATABLE_COLUMNS 它可列出用户定义的表或视图中可以被修改的所有列。这对我们是非常有用的:当你有一个视图你想对其进行更新操作,但是你又不确定哪些列是可以更新的,可时你就可以用数据字典视图 USER_UPDATABLE_COLUMNS
DESC USER_UPDATABLE_COLUMNS

 

 

 

 Name           Null?    Type

 

 -------------- -------- -------------

 

 OWNER          NOT NULL VARCHAR2(30)

 

 TABLE_NAME     NOT NULL VARCHAR2(30)

 

 COLUMN_NAME    NOT NULL VARCHAR2(30)

 

 UPDATABLE               VARCHAR2(3)

 

 INSERTABLE              VARCHAR2(3)

 

 DELETABLE               VARCHAR2(3)

 

看一个例子:

 

SELECT * FROM USER_UPDATABLE_COLUMNS

 

WHERE TABLE_NAME = 'V_RTLR_EMP';

 

 

 

OWNER   TABLE_NAME    COLUMN_NAME      UPD INS DEL

 

------- ------------- ---------------- --- ---

 

DEMO    V_RTLR_EMP    RTLR_NBR         YES YES YES

 

DEMO    V_RTLR_EMP    NAME             YES YES YES

 

DEMO    V_RTLR_EMP    CITY             YES YES YES

 

DEMO    V_RTLR_EMP    EMP_ID           NO  NO  NO

 

DEMO    V_RTLR_EMP    SALESPERSON_ID   YES YES YES

 

DEMO    V_RTLR_EMP    SALES_REP        NO  NO  NO

 

除此之外还有 ALL_UPDATABLE_COLUMNS 可以列出所有你可以访问的视图的可编辑列, DBA_UPDATABLE_COLUMNS( 只有 DBA 可以使用 ) 可以列出数据库中所有视图的可编辑列。

 

 

2.7.1 WITH CHECK OPTION 的影响

 

WITH CHECK OPTION 是创建视图指令的一个选项指令,它可以防止你对不存在于视图中的数据做任何更新。举例,如果你有一个视图像下面的定义:

CREATE VIEW emp_20 AS

 

SELECT * FROM employee

 

WHERE dept_id = 20

 

WITH CHECK OPTION;

 

对这个视图进行作操时,你不能插入 dept_id=30 的行 , 也不能把已经存在的行的 dept_id 更新成 30;

 

INSERT INTO emp_20 VALUES

 

(8765, 'SANJAY','MISHRA', 30, 7656, 4000, '01-JAN-88', 765);

 

INSERT INTO emp_20 VALUES

 

            *

 

ERROR at line 1:

 

ORA-01402: view WITH CHECK OPTION where-clause violation

 

 

 

UPDATE emp_20 SET dept_id = 30;

 

UPDATE emp_20 SET dept_id = 30

 

       *

 

ERROR at line 1:

 

ORA-01402: view WITH CHECK OPTION where-clause violation

 

因为被 WITH CHECK OPTION 定义的视图 而这个视图 emp_20 中只有 dept_id=20 的数据 , 所以不允许对此视图中不存在的数据进行更新 !

 

如果连接视图 (join view) 创建时使用了 WITH CHECK OPTION 定义 , 则该连接视图不允许插入操作 , 即使你是对键保护 ( key-preserved) 表进行插入 :

CREATE VIEW v_rtlr_emp_wco AS

 

SELECT c.rtlr_nbr, c.name, c.city, c.salesperson_id, e.lname sales_rep

 

FROM retailer c JOIN employee e

 

ON c.salesperson_id = e.emp_id

 

WITH CHECK OPTION;

 

 

 

View created.

 

 

 

INSERT INTO v_rtlr_emp_wco (rtlr_nbr, name, salesperson_id)

 

VALUES (345, 'X-MART STORES', 7820);

 

INSERT INTO v_rtlr_emp_wco (rtlr_nbr, name, salesperson_id)

 

                            *

 

ERROR at line 1:

 

ORA-01733: virtual column not allowed here

 

 

WITH CHECK OPTION 对于连接视图的删除操作不保护 :

 

DELETE FROM v_rtlr_emp_wco

 

WHERE rtlr_nbr = 215;

 

1 row deleted.

 

然而如果你的连接视图中是自我连接 (self join) 的键保护 ( key-preserved) , 则不能删除 :

 

CREATE VIEW emp_mgr_wco AS

 

SELECT e.lname employee, e.salary salary, m.lname manager

 

FROM employee e, employee m

 

WHERE e.manager_emp_id = m.emp_id

 

WITH CHECK OPTION;

 

 

 

View created.

 

 

 

DELETE FROM emp_mgr_wco WHERE employee = 'JONES';

 

DELETE FROM emp_mgr_wco WHERE employee = 'JONES'

 

            *

 

ERROR at line 1:

 

ORA-01752: cannot delete from view without exactly one key-preserved table

 

如果一个连接视图创建时使用了 WITH CHECK OPTION 刚你不可以对视图中的任何列进行修改 :

 

UPDATE v_rtlr_emp_wco

 

SET salesperson_id = 7784

 

WHERE rtlr_nbr = 215;

 

SET salesperson_id = 7784

 

    *

 

ERROR at line 2:

 

ORA-01733: virtual column not allowed here

 

在上面的例子上 , 显然是报错了 , 同样在自我连接 (self join) 的键保护 ( key-preserved) 表创建的视图中使用更新操作会得到同样的错误 :

 

UPDATE emp_mgr_wco

 

SET salary = 4800

 

WHERE employee = 'JONES';

 

SET salary = 4800

 

    *

 

ERROR at line 2:

 

ORA-01733: virtual column not allowed here