`
hackbomb
  • 浏览: 213392 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

ORACLE UPDATE 语句语法与性能分析

    博客分类:
  • SQL
阅读更多

为了方便起见,建立了以下简单模型,和构造了部分测试数据:
在某个业务受理子系统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)

   如何理解 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
   )

分享到:
评论

相关推荐

    ORACLE UPDATE 语句语法与性能分析看法

    ORACLE UPDATE 语句语法与性能分析看法

    ORACLE_UPDATE_语句语法与性能分析

    ORACLE_UPDATE_语句语法与性能分析

    oracle 多表做update insert语句.docx

    今天,我们将讨论 Oracle 中的 Update 语句,包括 Update 语句的基本语法、Update 语句中使用 Select 语句、Update 语句中使用 Join 语句、Insert 语句的使用等。 一、Update 语句的基本语法 Update 语句的基本...

    Oracle数据查询语句执行过程分析.pdf

    本文将详细分析 Oracle 数据查询语句执行过程,包括语法分析、执行语句和读取数据三个阶段。 一、语法分析阶段 语法分析阶段是 Oracle 数据查询语句执行过程中最耗时间的阶段。该阶段包括创建游标、分析语句、验证...

    ORACLE和SQL Server的语法区别

    1. 验证所有 SELECT、INSERT、UPDATE 和 DELETE 语句的语法是有效的。进行任何必要的修改。 2. 把所有外部联接改为 SQL-92 标准外部联接语法。 3. 用相应 SQL Server 函数替代 Oracle 函数。 4. 检查所有的比较...

    Oracle_PLSQL_语法详细手册

    五、 UPDATE语句: 9 六、 DELETE语句: 10 七、 TRUNCATE语句: 11 八、 各类FUNCTIONS: 12 1. 转换函数: 12 2. 日期函数 16 3. 字符函数 20 4. 数值函数 28 5. 单行函数: 33 6. 多行函数 35 第二部分 PL/SQL语法部分 ...

    oracle存储过程语法.pdf

    Oracle 存储过程语法详解 Oracle 存储过程是一种编程对象,可以在 Oracle 数据库中执行复杂的逻辑操作。下面是 Oracle 存储过程语法的详细解释: 创建存储过程 存储过程的创建语法如下: ```sql CREATE OR ...

    oracle和SQL的语法区别

    1. 验证所有 SELECT、INSERT、UPDATE 和 DELETE 语句的语法是有效的。进行任何必要的修改。 2. 把所有外部联接改为 SQL-92 标准外部联接语法。 3. 用相应 SQL Server 函数替代 Oracle 函数。 4. 检查所有的比较...

    SQLServer与Oracle语法差异汇总.docx

    从存储过程 自定义函数格式 游标 变量 赋值 语句结束符 大小写 Select 语法 Update语法 Delete语法 动态SQL语句 TOP用法 等各方面对比两个数据库的差异

    oracle基础语法培训.ppt

    SELECT语句 INSERT语句 UPDATE语句 DELETE删除 常用函数

    Sql Server与Oracle的区别

    1. 验证所有 SELECT、INSERT、UPDATE 和 DELETE 语句的语法是有效的。进行任何必要的修改。 2. 把所有外部联接改为 SQL-92 标准外部联接语法。 3. 用相应 SQL Server 函数替代 Oracle 函数。 4. 检查所有的比较...

    MySQL与Oracle的语法区别详细对比

    Oracle和mysql的一些简单命令对比 1) SQL&gt; select to_char(sysdate,’yyyy-mm-dd’) from dual; SQL&gt; select to_char(sysdate,’hh24-mi-ss’) from dual; mysql&gt; select date_format(now(),’%Y-%m-%d’); mysql&gt; ...

    SQL语句生成及分析器(中文绿色)

    1、支持绝大部分数据库,包括 大型数据库Oracle,Sybase(包括SQL AnyWhere),DB2,MS_SQL 中型数据库MS_Access,MySQL 桌面型数据库Paradox,DBF系列数据库... 10.4 简单SQL查询语句转换为Delete,Update,Insert语句

    oracle语法及函数大全.pdf

    Oracle 语法及函数大全 Oracle 是一种关系数据库管理系统,提供了强大的数据存储和管理功能。本文档总结了 Oracle 语法及函数大全,涵盖了数据操作、数据定义、数据控制、事务控制、程序化 SQL 等方面的知识点。 ...

    SQL语句生成及分析器

    该工具的主要特色: 1、支持几乎所有类型的数据库, ...6、支持将SQL查询语句,替换为插入(Insert into)和更新(Update)语句 7、附属工具内嵌入Delphi IDE(支持Delphi 5和Delphi 6) 8、文件拖放(SQL和TXT文件)

    oracle语法及函数大全[参考].pdf

    Oracle 语法及函数大全 Oracle 语法及函数大全是 Oracle 数据库管理系统中使用的语法和函数的集合。了解这些语法和函数是使用 Oracle 数据库的关键。 数据操作 * SELECT 语句:从数据库表中检索数据行和列。 * ...

    在Delphi中更新数据库UPDATE语句使用示例

    一个Delphi例子,配合Access数据库实现Delphi中的UPDATA数据更新实例,其实是演示如何使用SQL的Update语句,是一个数据库范畴的例子,Delphi高手请跳过,新手可下载源码学习。 运行环境:Delphi+Access

    Oracle游标使用方法及语法大全

    游标中的子查询语法与 SQL 中的子查询语法相同,例如: ```sql DECLARE CURSOR c_emp IS SELECT * FROM emp WHERE sal &gt; (SELECT AVG(sal) FROM emp); ``` 这里声明了一个名为 c_emp 的游标,该游标用于查询 emp 表...

    sql语句生成与分析器.rar

    11.4 简单SQL查询语句转换为Delete,Update,Insert语句 11.5 复制为字符串(支持对Java、C#、Delphi、VB、PowerBuilder开发语言的支持) 11.6 灵活的拖放功能 11.7 在线版本更新 11.8 查询结果输出为SQL脚本...

    Oracle笔试题及答案

    常用的SQL语句包括SELECT语句、INSERT语句、UPDATE语句、DELETE语句等。了解SQL语句的语法和用法是非常重要的。 3. 连接操作:Oracle数据库支持多种连接操作,如INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL OUTER ...

Global site tag (gtag.js) - Google Analytics