Update视图数据(oracle)

本文通过实验展示了在Oracle数据库中如何对包含单表或多表连接的视图进行数据更新。介绍了使用/*+ BYPASS_UJVC */ hint来绕过唯一性检查的方法。

  一般说起视图第一反应就是无法对其中数据进行修改,如果视图只包含一张表,应该是可以update的,因为SQL会执行查询转换,将视图转成表。但是多数的视图都是多表关联,那如何对视图中的数据进行update?

     下面是某个小实验:

SQL> create table t1 as select * from dba_objects;
 
表已创建。
SQL> create table t2 as select * from dba_objects;
表已创建。
 
 
 -- 可以看到单个表建视图,是可以update
SQL> create or replace view v_test as select * from t1;
视图已创建。
SQL> update v_test set subobject_name=owner;
已更新50593行。
SQL> commit;
提交完成。
 
 
-- 多个表建视图,需要加hint BYPASS_UJVC后才能update成功
SQL> create or replace view v_test as select t1.* from
  2  t1,t2 where t1.object_id=t2.object_id;
视图已创建。
SQL> update v_test set subobject_name=owner;
update v_test set subobject_name=owner                  *
第 1 行出现错误:
ORA-01779: 无法修改与非键值保存表对应的列
 
SQL> update /*+ BYPASS_UJVC */v_test set subobject_name=owner;
已更新50592行。
SQL> commit;
提交完成。
    
 
SQL> create or replace view v_test as select t1.object_id,t2.subobject_name,
  2  t1.owner from
  3  t1,t2 where t1.object_id=t2.object_id;
视图已创建。
SQL> update /*+ BYPASS_UJVC */v_test set subobject_name=owner;
已更新50592行。
SQL> commit;
提交完成。
  通过实验可以看出使用/*+ BYPASS_UJVC */可以完成对视图中数据的update操作。

  /*+ BYPASS_UJVC */在该语句中的作用则是屏蔽掉对 唯一约束的检索

   如果能确保视图中的数据唯一性则可以直接对视图中数据进行update。



 

Oracle 数据库中,视图(View)是一个虚拟表,它基于一个或多个表的查询结果。通常情况下,视图本身并不存储数据,而是从底层的基表中动态检索数据。因此,更新视图中的数据实际上是对这些基表进行更新。 要成功地更新视图数据,需要满足以下几个条件: 1. **视图必须是可更新的**:如果视图包含聚合函数(如 `SUM`、`COUNT`)、分组(`GROUP BY`)、集合操作符(如 `UNION`、`INTERSECT`)或者子查询,则该视图通常是不可更新的。 2. **更新语句只能影响一个基表**:如果视图连接了多个表,并且更新语句会影响多个表,则此更新将无法执行。 3. **视图定义中不能使用 `ROWNUM` 或伪列**:例如 `ROWNUM` 和 `ROWID` 会导致视图不可更新。 4. **基表字段必须存在于视图中**:如果你希望更新某个字段,该字段必须包含在视图的定义中。 ### 示例 假设有一个简单的视图 `employee_view`,其定义如下: ```sql CREATE OR REPLACE VIEW employee_view AS SELECT employee_id, first_name, last_name, salary FROM employees; ``` 可以通过以下 SQL 语句更新视图中的数据: ```sql UPDATE employee_view SET salary = salary * 1.1 WHERE employee_id = 101; ``` 这条语句会将 `employees` 表中 `employee_id` 为 `101` 的记录的薪资提高 10%。由于视图没有包含任何复杂的逻辑,它直接映射到单个表,因此可以成功更新。 ### 使用 `INSTEAD OF` 触发器处理复杂视图更新 对于涉及多个表的复杂视图,可以通过创建 `INSTEAD OF` 触发器来实现更新操作。例如,假设有两个表 `orders` 和 `customers`,并创建了一个联合视图 `order_customer_view`: ```sql CREATE OR REPLACE VIEW order_customer_view AS SELECT o.order_id, c.customer_id, c.name, o.amount FROM orders o JOIN customers c ON o.customer_id = c.customer_id; ``` 在这种情况下,直接更新视图可能会失败,因为 Oracle 无法确定如何修改底层的多张表。这时可以使用 `INSTEAD OF` 触发器: ```sql CREATE OR REPLACE TRIGGER update_order_customer INSTEAD OF UPDATE ON order_customer_view BEGIN -- 更新客户信息 IF :NEW.name != :OLD.name THEN UPDATE customers SET name = :NEW.name WHERE customer_id = :NEW.customer_id; END IF; -- 更新订单金额 IF :NEW.amount != :OLD.amount THEN UPDATE orders SET amount = :NEW.amount WHERE order_id = :NEW.order_id; END IF; END; / ``` 通过这种方式,即使视图涉及多个表,也可以自定义具体的更新逻辑。 需要注意的是,在启用某些功能时(如闪回日志等),数据库会产生额外的开销,因为系统必须记录所有对数据的更改以便支持恢复操作 [^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值