原文:http://dev.csdn.net/article/72/72686.shtm

为了方便起见,建立了以下简单模型,和构造了部分测试数据:
  在某个业务受理子系统BSS中,
  --客户资料表

  create table customers
  (
   customer_id   number(8)    not null,  -- 客户标示
   city_name     varchar2(10) not null,  -- 所在城市
   customer_type char(2)      not null,  -- 客户类型
 
   ...
  )

create unique index PK_customers on customers (customer_id)
  由于某些原因,客户所在城市这个信息并不什么准确,但是在
  客户服务部的CRM子系统中,通过主动服务获取了部分客户20%的所在
  城市等准确信息,于是你将该部分信息提取至一张临时表中:

  create table tmp_cust_city
  (
   customer_id    number(8) not null,
   citye_name     varchar2(10) not null,
   customer_type  char(2)   not null
  ) 

1) 最简单的形式
   --经确认customers表中所有customer_id小于1000均为'北京'
   --1000以内的均是公司走向全国之前的本城市的老客户:)

   update customers
   set    city_name='北京'
   where  customer_id<1000 

2) 两表(多表)关联update -- 仅在where字句中的连接
   --这次提取的数据都是VIP,且包括新增的,所以顺便更新客户类别

   update customers  a       -- 使用别名
   set    customer_type='01' --01 为vip,00为普通
   where  exists (select 1 
                  from   tmp_cust_city b
                  where  b.customer_id=a.customer_id
                 ) 

3) 两表(多表)关联update -- 被修改值由另一个表运算而来

   update customers a   -- 使用别名
   set    city_name=(select b.city_name from tmp_cust_city b where b.customer_id=a.customer_id)
   where  exists (select 1 
                  from   tmp_cust_city b
                  where  b.customer_id=a.customer_id
                 )
   -- update 超过2个值
   update customers a   -- 使用别名
   set    (city_name,customer_type)=(select b.city_name,b.customer_type 
                                     from   tmp_cust_city b 
                                     where  b.customer_id=a.customer_id)
   where  exists (select 1 
                  from   tmp_cust_city b
                  where  b.customer_id=a.customer_id
                 ) 

注意在这个语句中,
                                   =(select b.city_name,b.customer_type 
                                     from   tmp_cust_city b 
                                     where  b.customer_id=a.customer_id
                                    )
   与
                 (select 1 
                  from   tmp_cust_city b
                  where  b.customer_id=a.customer_id
                 )
   是两个独立的子查询,查看执行计划可知,对b表/索引扫描了2篇;
   如果舍弃where条件,则默认对A表进行全表
   更新,但由于(select b.city_name from tmp_cust_city b where where  b.customer_id=a.customer_id)
   有可能不能提供"足够多"值,因为tmp_cust_city只是一部分客户的信息,
   所以报错(如果指定的列--city_name可以为NULL则另当别论):
   
01407, 00000, "cannot update (%s) to NULL"
// *Cause:
// *Action:

一个替代的方法可以采用:
   update customers a   -- 使用别名
   set    city_name=nvl((select b.city_name from tmp_cust_city b where b.customer_id=a.customer_id),a.city_name)
   或者
   set    city_name=nvl((select b.city_name from tmp_cust_city b where b.customer_id=a.customer_id),'未知')
   -- 当然这不符合业务逻辑了

4) 上述3)在一些情况下,因为B表的纪录只有A表的20-30%的纪录数,
   考虑A表使用INDEX的情况,使用cursor也许会比关联update带来更好的性能:

set serveroutput on

declare
    cursor city_cur is
    select customer_id,city_name
    from   tmp_cust_city
    order by customer_id;
begin
    for my_cur in city_cur loop

update customers
        set    city_name=my_cur.city_name
        where  customer_id=my_cur.customer_id;
       
       /** 此处也可以单条/分批次提交,避免锁表情况 **/
--     if mod(city_cur%rowcount,10000)=0 then
--        dbms_output.put_line('----');
--        commit;
--     end if;
    end loop;
end;

5) 关联update的一个特例以及性能再探讨
   在oracle的update语句语法中,除了可以update表之外,也可以是视图,所以有以下1个特例:

    update (select a.city_name,b.city_name as new_name
            from   customers a,
                   tmp_cust_city b
            where  b.customer_id=a.customer_id
           )
    set    city_name=new_name

这样能避免对B表或其索引的2次扫描,但前提是 A(customer_id) b(customer_id)必需是unique index
    或primary key。否则报错:
    
01779, 00000, "cannot modify a column which maps to a non key-preserved table"
// *Cause: An attempt was made to insert or update columns of a join view which
//         map to a non-key-preserved table.
// *Action: Modify the underlying base tables directly.

6)oracle另一个常见错误
   回到3)情况,由于某些原因,tmp_cust_city customer_id 不是唯一index/primary key

   update customers a   -- 使用别名
   set    city_name=(select b.city_name from tmp_cust_city b where b.customer_id=a.customer_id)
   where  exists (select 1 
                  from   tmp_cust_city b
                  where  b.customer_id=a.customer_id
                 ) 

当对于一个给定的a.customer_id
   (select b.city_name from tmp_cust_city b where b.customer_id=a.customer_id)
   返回多余1条的情况,则会报如下错误:
   
01427, 00000, "single-row subquery returns more than one row"
// *Cause:
// *Action:

一个比较简单近似于不负责任的做法是
   update customers a   -- 使用别名
   set    city_name=(select b.city_name from tmp_cust_city b where b.customer_id=a.customer_id and rownum=1)

如何理解 01427 错误,在一个很复杂的多表连接update的语句,经常因考虑不周,出现这个错误,
   仍已上述例子来描述,一个比较简便的方法就是将A表代入 值表达式 中,使用group by 和
   having 字句查看重复的纪录

   (select b.customer_id,b.city_name,count(*)
    from tmp_cust_city b,customers a 
    where b.customer_id=a.customer_id
    group by b.customer_id,b.city_name
    having count(*)>=2
   )

转载于:https://www.cnblogs.com/ungshow/archive/2009/06/08/1498779.html

[转]Oracle update用例相关推荐

  1. oracle有的表带$,Oracle Update

    在表的更新操作中,在很多情况下需要在表达式中引用要更新的表以外的数据.象sql server提供了update的from 子句,可以将要更新的表与其它的数据源连接起来.虽然只能对一个表进行更新,但是通 ...

  2. Oracle HR 样例用户的建立 10g,11g均可

    Oracle HR 样例用户的建立 10g,11g均可 先将附件(见文章尾部)上的 10 个 .sql 文件放入这个路径中 : $ORACLE_HOME/demo/schema/human_resou ...

  3. Oracle数据库管理每周一例-第十七期 ADG

    Oracle数据库管理每周一例(12.2,18c,19c) 2020-10-16 第十七期 ADG 1.概念 2.环境说明 3.搭建流程-主库处理 1.配置静态监听 2.配置本地命名 3.数据库参数配 ...

  4. Oracle数据库之oracle update set select from 关联更新

    本文主要向大家介绍了Oracle数据库之oracle update set select from 关联更新,通过具体的内容向大家展现,希望对大家学习Oracle数据库有所帮助. 工作中有个需求,现在 ...

  5. oracle update错误后回退

    oracle update,delete并commit误操作后,利用闪回方法 flashback还原上个时间点的数据 Oracle Flashback 查询时间节点 select id, name, ...

  6. Oracle数据库管理每周一例-第十四期 19c需要调整的参数及操作

    Oracle数据库管理每周一例(12.2,18c,19c) 2020-09-13 第十四期 19c需要调整的参数及操作 1.说明 2.需要调整的参数 3.补丁 下期预告: 第十四期 19c需要调整的参 ...

  7. Oracle恢复一例--ORA-03113、ORA-24324,ORA-01041错误

    Oracle恢复一例--ORA-03113ORA-24324,ORA-01041错误 背景: 今天晚上上完OCM的课程后,有个OCP和高可用学员求助于麦老师.他的库是Windows 10.2.0.1的 ...

  8. Oracle数据库管理每周一例-第十五期 一些工具和小技巧

    Oracle数据库管理每周一例(12.2,18c,19c) 2020-09-20 第十五期 一些工具和小技巧 1.EMCC 2.MOS 3.其他一些工具和技巧 下期预告: 第十五期 一些工具和小技巧 ...

  9. oracle update from多表性能优化一例

    这几天测试java内存数据库,和oracle比较时发下一个update from语句很慢,如下: update business_newset fare1_balance_ratio = (selec ...

最新文章

  1. 感知不强又徒增功耗?为何今年5G手机也这么重视AI
  2. Android HTTP必知必会
  3. Csv解析CsvFile
  4. 同学,要不要来挑战双11零点流量洪峰?
  5. 让页面高度自动到底部 始终底部
  6. matlab vision hdl,MATLAB下载,MATLAB购买,MATLAB试用,MATLAB介绍,MATLAB评价
  7. NPM ---- 安装yarn
  8. 讨论一下hibernate如何动态注册一个动态生成的实体类
  9. H264视频压缩算法简析
  10. ESP-8266wifi模块获取网络实时时间
  11. 深度解读华为5G空口新技术:F-OFDM和SCMA
  12. 计算机关机怎么按,按什么键电脑关机
  13. 浏览器扩展插件:「油猴」使用详解 ( Tampermonkey )
  14. (数据结构)树的深度/高度
  15. android 市场 上传,安卓市场APP上传流程及审核要求
  16. 云计算技术的概念、原理
  17. python递归算法 - 汉诺塔问题
  18. REVIT建模步骤中:绘制形状不能拾取两条参照平面的交点解决方法
  19. 路由器DNS被篡改怎么办?如何看路由器是否被劫持
  20. c语言char a 4,char a:4;是什么意思C++

热门文章

  1. Oracle:容器数据库简介
  2. 第六届蓝桥杯JavaC组省赛真题——详细答案对照(包含垒骰子)
  3. 一天学完spark的Scala基础语法教程一、基础语法与变量(idea版本)
  4. 大数据NoSQL技术之Couchbase Server数据库详解
  5. MMM for MySQL FAQ
  6. 查看MongoDB索引的使用,管理索引
  7. Oracle里面的用户user无法登录 LOCKED(TIMED)
  8. phpstorm知识点
  9. 《训练指南》——6.10
  10. 提升PHP性能的21种方法