`
nlslzf
  • 浏览: 1026286 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

分析总结:关于两个表关联进行更新

阅读更多
http://www.oracle.com.cn/viewthread.php?tid=112596&highlight=%2Bwait4me
关于两个表关联进行更新,在论坛上经常有人问这个问题。尤其是不少刚刚从sql server转到oracle的
朋友,会把两种数据库的语法混淆。今天正好做了个测试,纪录下来
OS: RedHat Linus AS4
DB: Oracle 10gR2
案例:经典的detp/emp表,现在希望把emp.ename更新成ename+loc的形式。其中loc是通过关联emp和dept
取得的数据。

Last login: Mon Jan 22 15:40:57 2007 from 192.168.10.100
[oracle@testsrv1 ~]$ sqlplus /nolog
[uniread] Loaded history (3738 lines)

SQL*Plus: Release 10.2.0.1.0 - Production on Mon Jan 22 16:19:30 2007

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

idle> conn test/test
Connected.

准备数据的sql如下
复制内容到剪贴板
代码:
test@DW> !cat /tmp/pre.sql
drop table emp;
drop table dept;
CREATE TABLE dept (
      deptno        NUMBER(4),
      dname         VARCHAR2(14),
      loc           VARCHAR2(13));

CREATE TABLE emp (
      empno        NUMBER(4) ,
      ename        VARCHAR2(100),
      job          VARCHAR2(9),
      mgr          NUMBER(4),
      sal          NUMBER(7,2),
      comm         NUMBER(7,2),
      deptno       NUMBER(2)
      );

insert into dept  select * from scott.dept;

insert into emp select empno,ename,job,mgr,sal,comm,deptno  from scott.emp;

commit;

exec dbms_stats.gather_table_stats(user,'DEPT',cascade=>true);
exec dbms_stats.gather_table_stats(user,'EMP',cascade=>true);
原始数据如下
test@DW> select * from emp;

     EMPNO ENAME      JOB              MGR        SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902        800                    20
      7499 ALLEN      SALESMAN        7698       1600        300         30
      7521 WARD       SALESMAN        7698       1250        500         30
      7566 JONES      MANAGER         7839       2975                    20
      7654 MARTIN     SALESMAN        7698       1250       1400         30
      7698 BLAKE      MANAGER         7839       2850                    30
      7782 CLARK      MANAGER         7839       2450                    10
      7788 SCOTT      ANALYST         7566       3000                    20
      7839 KING       PRESIDENT                  5000                    10
      7844 TURNER     SALESMAN        7698       1500          0         30
      7876 ADAMS      CLERK           7788       1100                    20
      7900 JAMES      CLERK           7698        950                    30
      7902 FORD       ANALYST         7566       3000                    20
      7934 MILLER     CLERK           7782       1300                    10

14 rows selected.

test@DW> select * from dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

使用下面的语法(语法1)达到目的(注意,该语法有潜在的错误)
test@DW> update emp e set e.ename=e.ename ||'.'||(select d.loc from dept d where e.deptno=d.deptno);

test@DW> select * from emp;

     EMPNO ENAME                          JOB              MGR        SAL       COMM     DEPTNO
---------- ------------------------------ --------- ---------- ---------- ---------- ----------
      7369 SMITH.DALLAS                   CLERK           7902        800                    20
      7499 ALLEN.CHICAGO                  SALESMAN        7698       1600        300         30
      7521 WARD.CHICAGO                   SALESMAN        7698       1250        500         30
      7566 JONES.DALLAS                   MANAGER         7839       2975                    20
      7654 MARTIN.CHICAGO                 SALESMAN        7698       1250       1400         30
      7698 BLAKE.CHICAGO                  MANAGER         7839       2850                    30
      7782 CLARK.NEW YORK                 MANAGER         7839       2450                    10
      7788 SCOTT.DALLAS                   ANALYST         7566       3000                    20
      7839 KING.NEW YORK                  PRESIDENT                  5000                    10
      7844 TURNER.CHICAGO                 SALESMAN        7698       1500          0         30
      7876 ADAMS.DALLAS                   CLERK           7788       1100                    20
      7900 JAMES.CHICAGO                  CLERK           7698        950                    30
      7902 FORD.DALLAS                    ANALYST         7566       3000                    20
      7934 MILLER.NEW YORK                CLERK           7782       1300                    10

14 rows selected.

test@DW> rollback;

Rollback complete.

为什么刚才说语法1有潜在的错误?因为在上面的例子中,两个表的关联部分没有unique属性,那么就可能出现一个
emp.deptno对应多个dept.deptno的情况。这里仅仅是可能出现,因为当这个情况出现的时候,大多是因为原始数据
中存在重复的,多余的数据。

那么,为了简单的避免上面的问题,我们使用语法2,加上一个max函数达到唯一的目的
test@DW> update emp e set e.ename=e.ename ||'.'||(select max(d.loc) from dept d where e.deptno=d.dep
tno);

14 rows updated.

test@DW> rollback;
test@DW> select * from emp;

     EMPNO ENAME                          JOB              MGR        SAL       COMM     DEPTNO
---------- ------------------------------ --------- ---------- ---------- ---------- ----------
      7369 SMITH.DALLAS                   CLERK           7902        800                    20
      7499 ALLEN.CHICAGO                  SALESMAN        7698       1600        300         30
      7521 WARD.CHICAGO                   SALESMAN        7698       1250        500         30
      7566 JONES.DALLAS                   MANAGER         7839       2975                    20
      7654 MARTIN.CHICAGO                 SALESMAN        7698       1250       1400         30
      7698 BLAKE.CHICAGO                  MANAGER         7839       2850                    30
      7782 CLARK.NEW YORK                 MANAGER         7839       2450                    10
      7788 SCOTT.DALLAS                   ANALYST         7566       3000                    20
      7839 KING.NEW YORK                  PRESIDENT                  5000                    10
      7844 TURNER.CHICAGO                 SALESMAN        7698       1500          0         30
      7876 ADAMS.DALLAS                   CLERK           7788       1100                    20
      7900 JAMES.CHICAGO                  CLERK           7698        950                    30
      7902 FORD.DALLAS                    ANALYST         7566       3000                    20
      7934 MILLER.NEW YORK                CLERK           7782       1300                    10

14 rows selected.

test@DW> rollback;

Rollback complete.

在重复数据比较多的情况下,我们不想使用了聚合函数max,那么可以使用语法3,加入rownum=1条件
test@DW> update emp e set e.ename=e.ename ||'.'||(select d.loc from dept d where e.deptno=d.deptno a
nd rownum=1);

14 rows updated.

test@DW> select * from emp;

     EMPNO ENAME                          JOB              MGR        SAL       COMM     DEPTNO
---------- ------------------------------ --------- ---------- ---------- ---------- ----------
      7369 SMITH.DALLAS                   CLERK           7902        800                    20
      7499 ALLEN.CHICAGO                  SALESMAN        7698       1600        300         30
      7521 WARD.CHICAGO                   SALESMAN        7698       1250        500         30
      7566 JONES.DALLAS                   MANAGER         7839       2975                    20
      7654 MARTIN.CHICAGO                 SALESMAN        7698       1250       1400         30
      7698 BLAKE.CHICAGO                  MANAGER         7839       2850                    30
      7782 CLARK.NEW YORK                 MANAGER         7839       2450                    10
      7788 SCOTT.DALLAS                   ANALYST         7566       3000                    20
      7839 KING.NEW YORK                  PRESIDENT                  5000                    10
      7844 TURNER.CHICAGO                 SALESMAN        7698       1500          0         30
      7876 ADAMS.DALLAS                   CLERK           7788       1100                    20
      7900 JAMES.CHICAGO                  CLERK           7698        950                    30
      7902 FORD.DALLAS                    ANALYST         7566       3000                    20
      7934 MILLER.NEW YORK                CLERK           7782       1300                    10

14 rows selected.

语法2和语法3有什么区别?我们来看看他们的执行计划

先看语法2
test@DW> explain plan for update emp e set e.ename=e.ename ||'.'||(select max(d.loc) from dept d whe
re e.deptno=d.deptno);

Explained.

test@DW> @/Oracle/product/10.2.1/rdbms/admin/utlxplp.sql

PLAN_TABLE_OUTPUT
--------------------
Plan hash value: 1667745622

----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | UPDATE STATEMENT    |      |    14 |   126 |     3   (0)| 00:00:01 |
|   1 |  UPDATE             | EMP  |       |       |            |          |
|   2 |   TABLE ACCESS FULL | EMP  |    14 |   126 |     3   (0)| 00:00:01 |
|   3 |   SORT AGGREGATE    |      |     1 |    11 |            |          |
|*  4 |    TABLE ACCESS FULL| DEPT |     1 |    11 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - filter("D"."DEPTNO"=:B1)

16 rows selected.

test@DW> rollback;

再来看看语法3
test@DW> explain plan for update emp e set e.ename=e.ename ||'.'||(select d.loc from dept d where e.
deptno=d.deptno and rownum=1);

Explained.

test@DW> @/Oracle/product/10.2.1/rdbms/admin/utlxplp.sql

PLAN_TABLE_OUTPUT
--------------------
Plan hash value: 764578432

----------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | UPDATE STATEMENT    |      |    14 |   126 |     3   (0)| 00:00:01 |
|   1 |  UPDATE             | EMP  |       |       |            |          |
|   2 |   TABLE ACCESS FULL | EMP  |    14 |   126 |     3   (0)| 00:00:01 |
|*  3 |   COUNT STOPKEY     |      |       |       |            |          |
|*  4 |    TABLE ACCESS FULL| DEPT |     1 |    11 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter(ROWNUM=1)
   4 - filter("D"."DEPTNO"=:B1)

17 rows selected.

仔细对比2和3的执行计划,他们唯一的区别在于:2使用了sort aggregate,而3使用了count stopkey

如果我们熟悉oracle分页算法,就知道count stopkey虽然名义上是全表扫描,但是在重复数据多的时候,会
根据指定的rownum=n在得到第n条纪录后停止扫描。而sort aggregate取得max,一定是执行全表扫描的。

通过这个细微的差别,我们可以判断出:当重复数据相对多的时候,使用rownum的语法3比语法2效率高(具体
高多少,这个需要实际测试)


===============================================================================
上面的讨论都是针对普通的表进行的,既没有任何约束条件的表关联。在实际操作中,我们更多情况面对的是
有主外键关系的表。那么,对我们的需求,又有了不同的解决方案

我们先给dept加上一个主键(实际上仅仅用唯一性约束就可以了)
test@DW> alter table dept add constraint pk_dept primary key (deptno);

或者直接使用唯一索引
test@DW> create unique index idx_dept on dept(deptno);

Table altered.

在现在的条件下,我们可以对视图(online view)直接进行更新操作。我们叫他语法4
test@DW> update (select ename,loc from emp,dept where emp.deptno=dept.deptno) v set v.ename=v.ename||'.'||v.loc;

14 rows updated.

在语法4中,我们先建立了一个online view,然后对她进行更新。一个包含多表的视图,是否可以更新,哪些字段
可以更新,涉及到一个叫 kep-preserved table的概念。简单的说,如果一个表的所有key同时也是视图的key,那么
这个表就是kep-preserved table。当视图中仅有一个kpt的时候,可以对kpt的数据进行更新操作。关于key-preseved
table和upatable columns的具体信息,请参考手册。

在我们的例子中,emp是key-preserved table,所以我们可以更新它的字段。
因为唯一索引,所以语法4的执行计划选择了使用索引,避免全表扫描
Execution Plan
----------------------------------------------------------
Plan hash value: 1686319074

-----------------------------------------------------------------------------------------
| Id  | Operation                     | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT              |         |    14 |   280 |     4   (0)| 00:00:01 |
|   1 |  UPDATE                       | EMP     |       |       |            |          |
|   2 |   NESTED LOOPS                |         |    14 |   280 |     4   (0)| 00:00:01 |
|   3 |    TABLE ACCESS FULL          | EMP     |    14 |   126 |     3   (0)| 00:00:01 |
|   4 |    TABLE ACCESS BY INDEX ROWID| DEPT    |     1 |    11 |     1   (0)| 00:00:01 |
|*  5 |     INDEX UNIQUE SCAN         | PK_DEPT |     1 |       |     0   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - access("EMP"."DEPTNO"="DEPT"."DEPTNO")


总结:根据上面的分析,我个人给出的建议是:
        1。如果满足updatable view的条件,优先使用语法4,更新onlien view
        2。如果没有必要的约束条件,优先使用rownum


如果出现null之类的问题,请确保两张表之间的数据不存在a中有而b没有的
分享到:
评论

相关推荐

    论文研究-灰色趋势关联分析及其应用.pdf

    给出了灰关联空间分解和灰色趋势关联分析的基本概念和方法 ,总结了用灰色趋势关联度进行系统分析的一般步骤 ,通过两个具体的实例研究分析了该方法的优越性和实用性.

    数据分析入门.pptx

    对比分析法 数据分析 对比分析法:将两个或两个以上的数据进行对比分析,分析其中的差异,从而揭示这些事物发展变化的规律和情况。 横向比较: 指对同类的不同对象在统一标准下进行比较的方法。要注意事物的可比性...

    论文研究-关联规则挖掘综述.pdf

    近年来国内外学者对关联规则进行了大量的研究,为深入理解关联...其次从串行和并行两个角度总结了关联规则挖掘的一般方法,概述并分析了一些典型的关联规则挖掘模式;最后讨论了关联规则挖掘质量改善问题及领域应用。

    系统分析师2002到2019年的试题总结

    1、面向对象分析中,一个事物发生变化会影响另一个事物,两个事物之间属于 ( )。 A、关联关系 B、依赖关系 C、实现关系 D、泛化关系 2、关于用例图中的参与者,说法正确的是( )。 A、参与者是与系统交互的事物,...

    Laravel5.1 框架模型多态关联用法实例分析

    简单的一句话总结:一张表对应两张表。 1 实现多态关联 1.1 文章表的结构 public function up() { Schema::create('articles', function (Blueprint $table) { $table->increments('id'); $table->st

    电商数据分析-电商数据分析导论-数据分析在电商中的应用.pdf

    电商数据分析导论 1.3数据分析在电商中的应用 1 业务场景 2 3 CONTENTS 数据诊断及复盘 市场分析 4 竞争分析及渠道分析 5 活动及广告分析 6 产品分析及库存分析 7 消费者分析 业务场景 PART ONE 业 务 场 景 数据...

    数据分析总结与感悟.pdf

    数据分析总结与感悟 数据分析总结与感悟 ⼩⽣今年研⼆,从事软件数据分析与挖掘不到两年。两年⾥⼩⽣忙忙碌碌,从来没有总结过⾃⼰的⼯作,今天暂停住忙碌的脚步,随意书写 ⼏⾏⽂字,权当忙⾥偷闲总结这两年数据...

    hive项目之微博ETL项目总结分析

    微博ETL项目分析 一、数据格式 文件格式 Txt Csv’ Xls Doc ...将两个类别下各自对应的文件集,进行解析、结构化。 通过load语法,将数据分别导入到两张表当中。 三、主要思路与考点 主要思路 通过ja

    常用数据分析方法.docx

    6、方差分析(ANOVA/Analysis of Variance) 又称"变异数分析"或"F检验",是R.A.Fisher发明的,用于两个及两个以上样本均数差别的显著性检验。由于各种因素的影响,研究所得的数据呈现波动状。造成波动的原因可分成两...

    数据分析的目的.doc

    关联分析:如果两个或多个事物之间存在一定的关联,那么其中一个事物就能通过其 他事物进行预测;它的目的是为了挖掘隐藏在数据间的相互关系; 4.因果分析:因果分析是为了确定引起某一现象变化原因的分析,主要解决...

    Java实现把两个数组合并为一个的方法总结

    主要介绍了Java实现把两个数组合并为一个的方法,结合实例形式总结分析了java常用的四种数组合并操作技巧,需要的朋友可以参考下

    跨境电商数据分析.pptx

    数据分析流程 关键数据: 客单价 客户满意度 用户回访率 投资回报率 独立用户访问量 积极访问者比率 忠实访问者比率 客户转化率 量化分析: 把两个相互联系的指标数据进行比较,从数量上展示和说明研究对象各种关系...

    数据分析(一):数据分析的意识.doc

    那影响应用市场排名的因素有哪些呢,不难查到,像应用的下载量、评价、星级等,那 在两个不同的时间点上到底发生了什么呢,去查一下应用对外的版本记录信息,信息不 是很多,但依然引起了我的注意: 比较可疑的是...

    浅谈数据分析.pdf

    数据分析 19 交叉分析法 综合评价分析法 将两个有一定联系的变量及其值交 叉排在一张表内,即二维交叉表 将多个指标转化为一个能够反映综合 情况的指标进行评价 比如: Y=ax 1 +bx 2 +cx 3 +dx 4 +… 矩阵关联分法 ...

    数据分析.doc

    数据挖掘常用的方法: 利用数据挖掘进行数据分析常用的方法主要有分类、回归分析、聚类、关联规则、特征 、变化和偏差分析、Web页挖掘等, 它们分别从不同的角度对数据进行挖掘。 1、分类 分类是找出数据库中一组...

    数据分析中的数据探索.docx

    Spearman秩相关系数 不服从正态分布的变量,分类或等级变量之间的关联性可采用Spearman秩相关系数 总结上述两者: 只要两个变量具有严格单调的函数关系,那么他们一定是完全Spearman相关,Person相关只有在变量具有...

    数据仓库与数据挖掘实验报告--.doc

    数据仓库和数据挖掘总结 38 4.1关联规则总结 38 4.2决策树总结 38 4.3聚类分析总结 40 第1章 数据仓库和数据挖掘简介 1.1数据简介 我的数据集是由两个不同的数据库组成,因为做关联规则的时候,影响小学生自控能 力...

    大数据实验报告总结体会-大数据挖掘流程及方法总结.pdf

    五、数据挖掘任务 关联分析 两个或两个以上变量的取值之间存在某种规律性,就称为关联。数据关联是数据库中存在的⼀类重要的、可被发现的知识。关联分为简单关 联、时序关联和因果关联。关联分析的⽬的是找出数据库...

    UML和模式应用(架构师必备).part01.rar

    2.4 如何进行迭代和进化式分析和设计 2.5 什么是风险驱动和客户驱动的迭代计划 2.6 什么是敏捷方法及其观点 2.7 什么是敏捷建模 2.8 什么是敏捷UP .2.9 UP的其他关键实践 2.10 什么是UP的阶段 2.11 什么是UP...

    UML和模式应用(架构师必备).part07.rar

    2.4 如何进行迭代和进化式分析和设计 2.5 什么是风险驱动和客户驱动的迭代计划 2.6 什么是敏捷方法及其观点 2.7 什么是敏捷建模 2.8 什么是敏捷UP .2.9 UP的其他关键实践 2.10 什么是UP的阶段 2.11 什么是UP...

Global site tag (gtag.js) - Google Analytics