在常用的SQL写法中我们会经常遇到把一个表的数据插入另外一张表的情况,这是一个insert into 表名 select .... from 表名   就可以解决了。但是如果是把一张表的数据同时插入两张表或两张以上的表该怎么办?你是不是已经想到了办法了,使用多个insert into
语句,例如:

insert into test1 select * from test;
insert into test2 select * from test;
......
commit;

通过把多张表的插入脚本放入一个事务中解决(如上),但是这样做的结果有可能是test1表和test2表结果集不一样,因为这个事务中插入的源数据表test被读取了两次,在一个表数据变化较快的情况下,两次读取的数据可能会不一样,这就违反了我们之前的需求。如何解决?? 这种情况下我们可以把原表数据预先读到的一个全局临时表里,然后再从临时表里读出数据插入多个目的表,当然,引入我们本文的话题,使用insert all更为方便解决。

insert all分为无条件插入和有条件插入,在有条件插入的情况下还可以使用insert first,他与insert all会有一点小区别,在下面的例子中我们将会介绍。

1,insert all无条件插入

---构造一个环境

SQL> drop table test;

Table dropped

SQL> drop table test1;

Table dropped

SQL> drop table test2;

Table dropped

SQL> create table test as select deptno,dname from dept;

Table created

SQL> create table test1 as select * from test where =;

Table created

SQL> create table test2 as select * from test where =;

Table created

SQL> select count(*) from test;

  COUNT(*)
---------- SQL> select count(*) from test1; COUNT(*)
---------- SQL> select count(*) from test1; COUNT(*)
----------

--插入数据

SQL> insert all
into test1(deptno,dname)
into test2(deptno,dname)
select deptno,dname from test; rows inserted SQL> select count(*) from test1; COUNT(*)
---------- SQL> select count(*) from test2; COUNT(*)
---------- SQL> commit; Commit complete

可以看到我们使用一个SQL语句实现了插入了多张表数据,而且这种方式要比写多个insert into 语句效率要高。在上面的SQL中不论插入多少张表,test表只会被读取一次。

2,带条件的insert all插入

SQL> select * from test;

DEPTNO DNAME
------ --------------
ACCOUNTING
RESEARCH
SALES
OPERATIONS SQL> truncate table test1; Table truncated SQL> truncate table test2; Table truncated SQL> insert all
when deptno < then
into test1(deptno,dname)
when deptno < then
into test2(deptno,dname)
select deptno,dname from test; rows inserted SQL> select * from test1; DEPTNO DNAME
------ --------------
ACCOUNTING
RESEARCH SQL> select * from test2; DEPTNO DNAME
------ --------------
ACCOUNTING
RESEARCH
SALES
OPERATIONS SQL> commit; Commit complete

从上面的SQL中我们可以当有带条件的插入后,因为test1和test2表对应的条件不同,插入到两张表的数据也不同,这说明插入条件起来作用。test1的条件是部门号小于30的放入test1表,test2的条件是部门号小于50的放入test2表,从test表中查出的4条数据,每条数据都经过了这两个条件的判断(过滤)。

3,带条件的insert fist插入

SQL> truncate table test1;

Table truncated

SQL> truncate table test2;

Table truncated

SQL> select * from test;

DEPTNO DNAME
------ --------------
ACCOUNTING
RESEARCH
SALES
OPERATIONS SQL> insert first
when deptno < then
into test1(deptno,dname)
when deptno < then
into test2(deptno,dname)
select deptno,dname from test; rows inserted SQL> select * from test1; DEPTNO DNAME
------ --------------
ACCOUNTING
RESEARCH SQL> select * from test2; DEPTNO DNAME
------ --------------
SALES
OPERATIONS SQL> commit; Commit complete

从test1和test2的结果输出我们会发现test1数据是正常的,而test2貌似数据少了,因为部门10、部门20也符合 deptno<50的条件,为什么没有插入进去那?其实不然,insert first是考虑先后关系的,如果有数据满足第一个when条件又满足第二个when条件,则执行第一个then插入语句,第二个then就不插入第一个then已经插入过的数据了。反之有数据不满足第一个when条件且满足第二个when条件,则数据会插入第二个条件下对应的表中,这也正是insert first与inset all的区别。

简单来说就是all只要满足条件,就会插入;first只要有一个满足条件,后面的条件不再判断。

注意:insert all 无法支持序列插入,会导致两边不一致,举例如下:

SQL> truncate table test1;

Table truncated

SQL> truncate table test2;

Table truncated

SQL> create sequence seq_test;

Sequence created

SQL> insert all
into test1(deptno,dname)
into test2(deptno,dname)
select seq_test.nextval deptno,dname from test; insert all
into test1(deptno,dname)
into test2(deptno,dname)
select seq_test.nextval deptno,dname from test ORA-: 此处不允许序号 --不能直接使用序列
SQL> CREATE OR REPLACE FUNCTION F_SEQ RETURN NUMBER AS
V_SEQ NUMBER;
BEGIN
SELECT SEQ_TEST.NEXTVAL INTO V_SEQ FROM DUAL;
RETURN V_SEQ;
END;
/ Function created SQL> insert all
into test1(deptno,dname)
into test2(deptno,dname)
select f_seq deptno,dname from test; rows inserted SQL> commit; Commit complete SQL> select * from test1; DEPTNO DNAME
------ --------------
ACCOUNTING
RESEARCH
SALES
OPERATIONS SQL> select * from test2; DEPTNO DNAME
------ --------------
ACCOUNTING
RESEARCH
SALES
OPERATIONS

从上面的SQL结果中我们可以看到test1和test2表deptno值出现了不一样,这就是说insert all 无法支持序列插入,会导致两边不一致。

可参考:

http://blog.itpub.net/29196873/viewspace-1122075/

http://blog.csdn.net/ghostgant/article/details/5700228

理解insert all/insert first的使用的更多相关文章

  1. PLSQL_性能优化系列08_Oracle Insert / Direct Insert性能优化

    2014-09-25 Created By BaoXinjian

  2. sql语句中的insert 和 insert into 的区别?into有什么用?

    insert into tableName values(........) insert tableName (字段名1,字段名2,...)values(......)看语句结构就知道区别了 .in ...

  3. Hive之insert和insert overwrite

    1. hive 表及数据准备 建表,并插入初始数据.向表中插入 hive> use test; hive> create table kwang_test (id int, name st ...

  4. innodb insert buffer 插入缓冲区的理解

    今天在做一个大业务的数据删除时,看到下面的性能曲线图 在删除动作开始之后,insert buffer 大小增加到140.对于这些状态参数的说明 InnoDB Insert Buffer 插入缓冲,并不 ...

  5. mysql insert一条记录后怎样返回创建记录的主键id,last_insert_id(),selectkey

    mysql插入数据后返回自增ID的方法 mysql和oracle插入的时候有一个很大的区别是,oracle支持序列做id,mysql本身有一个列可以做自增长字段,mysql在插入一条数据后,如何能获得 ...

  6. python pandas ---Series,DataFrame 创建方法,操作运算操作(赋值,sort,get,del,pop,insert,+,-,*,/)

    pandas 是基于 Numpy 构建的含有更高级数据结构和工具的数据分析包 pandas 也是围绕着 Series 和 DataFrame 两个核心数据结构展开的, 导入如下: from panda ...

  7. mysql insert一条记录后 返回创建记录主键id的方法

    mysql插入数据后返回自增ID的方法 mysql和oracle插入的时候有一个很大的区别是,oracle支持序列做id,mysql本身有一个列可以做自增长字段,mysql在插入一条数据后,如何能获得 ...

  8. 跟随一条insert语句, 进入TiDB的源码世界(上)

    TiDB是Google F1的开源实现: TiDB实现了基于mvcc的乐观锁,在线表结构变更,基于时间戳的数据线性一致性,等等: 为了可靠性,TiDB和Oracle一样,维护了百万级别的自动化测试用例 ...

  9. LeetCode 381. Insert Delete GetRandom O(1) - Duplicates allowed O(1) 时间插入、删除和获取随机元素 - 允许重复(C++/Java)

    题目: Design a data structure that supports all following operations in averageO(1) time. Note: Duplic ...

随机推荐

  1. Mongdb使用客户端

    安装Robomongo图形化管理工具 Robomongo是一个基于 Shell 的跨平台开源 MongoDB 管理工具.嵌入了 JavaScript 引擎和 MongoDB mogo . 只要你会使用 ...

  2. Liferay 6.2 改造系列之二十四:修改liferay密码的加密方式

    为了便于后期与Cas集成过程中使用数据库用户的方便,将liferay密码的加密方式改为SHA. 在/portal-master/portal-impl/src/portal.properties配置文 ...

  3. AngularJS学习之HTML DOM

    1.AngularJS为HTML DOM元素的属性提供了绑定应用数据的指令: 2.ng-disabled指令:直接绑定应用程序数据到HTML的disable属性: <div ng-app=&qu ...

  4. DOM--4 响应用户操作和事件(1)

    简介 事件:事件并不是以"on"开头的.例如,onclick引用的是一个对象的属性,click才是事件. 事件侦听器:当指定的事件发生时会执行的函数或方法. 事件注册:为DOM元素 ...

  5. Ubuntu12.04安装搜狗输入法失败后,出现登录界面循环

    前些天,因为复现别人实验就准备重新启用实验室的集群上的系统,上去安装了几个插件,之后又觉得需要中文输入法就试着装一下,结果安装失败,看到报错信息,也没放在心上,第二天启动时发现再也登录不进去. 现象描 ...

  6. jquery(ajax)与js(ajax)的比较

    原始js: function update_mess(){ var account_name = $("#account").val(); var xmlhttp; if(wind ...

  7. BZOJ1481 : Navigation Game

    设$f[i][j][k]$表示从最后一行某个$H$走到$(i,j)$且在第$i$行只经过了$(i,j)$,途中经过了$k$次$F$的最小代价. $A[i][j][k]$表示从下一行$\leq i$的某 ...

  8. BZOJ2769 : YY的快速排序

    将数字离散化并去重,则对于一对逆序对$i<j$,$a_i>a_j$,贡献为$\frac{2}{a_i-a_j+1}$,因此只要对于每个差值统计出对应的逆序对个数即可. 将序列分块,块内平方 ...

  9. 【BZOJ3450】Tyvj1952 Easy 期望DP

    [BZOJ3450]Tyvj1952 Easy Description 某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠运气:(我们来简化一下这个游戏的规则有n次点击要做,成功了就是 ...

  10. BZOJ1798[Ahoi2009]Seq 维护序列seq 题解

    题目大意: 有长为N的数列,有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值. ...