Oracle中的insert/insert all/insert first

lhrbest發表於2019-09-03

Oracle中的insert/insert all/insert first


1、概念

Oracle 中insert all 是指把 同一批 資料插入到 不同的表 中。


假如,現在有個需求,把表 t 的中資料分別插入到 t1、t2,如果你不知道 insert all, 你可能會使用 insert 插入 2 次,例如:


INSERT INTO t1(object_id, object_name) SELECT * FROM t;

INSERT INTO t2(object_id, object_name) SELECT * FROM t;

COMMIT;


其實,以上這樣的寫法,不一定正確。在 兩次 insert 過程中, 有可能 t 表的資料發生了改變,從而導致 t1、t2 表得到的資料不一樣,正確的寫法是用 insert all


INSERT ALL

   INTO t1(object_id, object_name)

   INTO t2(object_id, object_name)

SELECT * FROM t;

COMMIT;


1.1 思維導圖

在這裡插入圖片描述


1.2 基礎資料

DROP TABLE stu; -- if exists


CREATE TABLE stu (

   s_id NUMBER,

   s_xm VARCHAR2(30)

);


INSERT INTO stu(s_id, s_xm) VALUES (1, '小遊子');

INSERT INTO stu(s_id, s_xm) VALUES (2, '小優子');

INSERT INTO stu(s_id, s_xm) VALUES (3, '小倩子');

COMMIT;



2、例項分析

2.1 無條件插入

CREATE TABLE stu1 AS SELECT * from stu WHERE 1 = 2;

CREATE TABLE stu2 AS SELECT * from stu WHERE 1 = 2;


INSERT ALL

   INTO stu1(s_id, s_xm)

   INTO stu2(s_id, s_xm)

SELECT * FROM stu;

COMMIT;


SELECT * FROM stu1;

SELECT * FROM stu2;

在這裡插入圖片描述



2.2 有條件插入

2.2.1 insert first

對於每一行資料,只插入到 第一個when 條件成立的表,不繼續檢查其他條件。


DROP TABLE stu1; -- if exists

DROP TABLE stu2; -- if exists


CREATE TABLE stu1 AS SELECT * FROM stu WHERE 1 = 2;

CREATE TABLE stu2 AS SELECT * FROM stu WHERE 1 = 2;


INSERT FIRST 

  WHEN s_id <= 2 THEN 

     INTO stu1 (s_id, s_xm) 

  WHEN s_id >= 2 THEN -- 注意 2 是重複的哦

     INTO stu2 (s_id, s_xm)

SELECT * FROM stu;


SELECT * FROM stu1;

SELECT * FROM stu2;



測試結果:

在這裡插入圖片描述


2.2.2 insert all

對於每一行資料,對 每一個when 條件都進行檢查,如果滿足條件就執行插入操作。


-- 僅將上述 FIRST 改為 ALL

DROP TABLE stu1; -- if exists

DROP TABLE stu2; -- if exists


CREATE TABLE stu1 AS SELECT * FROM stu WHERE 1 = 2;

CREATE TABLE stu2 AS SELECT * FROM stu WHERE 1 = 2;


INSERT ALL

  WHEN s_id <= 2 THEN 

     INTO stu1 (s_id, s_xm) 

  WHEN s_id >= 2 THEN -- 注意 2 是重複的哦

     INTO stu2 (s_id, s_xm)

SELECT * FROM stu;


SELECT * FROM stu1;

SELECT * FROM stu2;


測試結果:

在這裡插入圖片描述



3、其他操作

3.1 行轉列插入

DROP TABLE stu1; -- if exists

DROP TABLE stu2; -- if exists


CREATE TABLE stu1 (

  s_id NUMBER,

  s_xm VARCHAR(30) -- 資料型別要一致哦

);


CREATE TABLE stu2 (

  s_id  NUMBER,

  s_xm1 VARCHAR2(30),

  s_xm2 VARCHAR2(30),

  s_xm3 VARCHAR2(30)

);


INSERT INTO stu2(s_id, s_xm1, s_xm2, s_xm3) VALUES (1, 'a1', 'b1', 'c1');

INSERT INTO stu2(s_id, s_xm1, s_xm2, s_xm3) VALUES (2, 'a2', 'b2', 'c2');

INSERT INTO stu2(s_id, s_xm1, s_xm2, s_xm3) VALUES (3, 'a3', 'b3', 'c3');


INSERT ALL

  INTO stu1 VALUES (s_id, s_xm1) 

  INTO stu1 VALUES (s_id, s_xm2)

  INTO stu1 VALUES (s_id, s_xm3)

SELECT * FROM stu2;


SELECT * FROM stu1;


測試結果:

在這裡插入圖片描述

————————————————




insert all官方文件解釋:


/*

多表插入語句的限制條件:

 1. 只能對錶執行多表插入語句,不能對檢視或物化檢視執行;

 2. 不能對遠端表執行多表插入語句;

 3. 不能使用表集合表示式;

 4. 不能超過999個目標列;

 5. 在RAC環境中或目標表是索引組織表或目標表上建有BITMAP索引時,多表插入語句不能並行執行;

 6. 多表插入語句不支援執行計劃穩定性;

 7. 多表插入語句中的子查詢不能使用序列。

*/


第一步:準備資料


CREATE TABLE t1(product_id NUMBER, product_name VARCHAR2(80),MONTH NUMBER);  


INSERT INTO t1 VALUES(111, '蘋果',1);  

INSERT INTO t1 VALUES(222, '橘子',1);  

INSERT INTO t1 VALUES(333, '香蕉',1);  




第二部:insert all


INSERT ALL  

    INTO t2   

    VALUES (product_id, product_name,MONTH)  

    INTO t2   

    VALUES (product_id, product_name,MONTH+1)  

    INTO t2   

    VALUES (product_id, product_name,MONTH+2)  

    INTO t2   

    VALUES (product_id, product_name,MONTH+3)   

SELECT product_id, product_name, MONTH  

FROM t1;  


這裡的表t2的資料下面會用到


---------------------------------------------------------------------------


第三步:有條件的insert all


insert all 

when month=1 then

into t3

when month=2 then 

into t4

else 

into t5

select product_id,product_name,month from t2;

commit;


-------------------------------------------------------------------------


第四部:insert first (需要講解下)


insert first 

when month=1 then

into t3 VALUES(product_id,product_name,month)  

when product_id=111 then 

into t4 VALUES(product_id,product_name,month)  

else 

into t5 VALUES(product_id,product_name,month)  

select product_id,product_name,month from t2;

commit;


--------------------------------------------------------------------------


根據第二部,t2表的資料做測試。


查詢t4表發現:少了一條 111 蘋果 1


111 蘋果2

111 蘋果 3

111 蘋果 4


總結:insert first 當資料滿足第一when 條件的時候,不會作用在下面的when條件了,

簡而言之:當一條資料滿足條件後,即使滿足後面的條件也不會插入資料庫。

正常情況:如果資料滿足所有的when條件,每個表都會插入該條資料,insert first 資料只會插入一個表。



無條件的插入

Oracle中的insert all是指把同一批資料插入到不同的表中,假如如今有個需求:把t表中的資料分別插入t1,t2,假設你不知道insert all,你可能會使用insert插入2次,例如以下所看到的:

insert  into t1(object_name,object_id) select * from t;
insert  into t2(object_name,object_id) select * from t;
commit;

其實,以上這樣的寫法是錯誤的,由於在兩次insert的過程中,t表的資料有可能已經發生了變化,也就是說,t1,t2表得到的資料有可能不一樣,正確的寫法應該是採用insert all:

insert all
into t1(object_name,object_id)
into t2(object_name,object_id)
select * from t;
commit;


有條件的插入

insert first/all 是對每一行來進行推斷
兩者差別:
insert first:對於每一行資料,僅僅插入到第一個when條件成立的表,不繼續檢查其它條件。
insert all : 對於每一行資料,對每個when條件都進行檢查,假設滿足條件就執行插入操作。 

看以下的樣例:

--insert first
--前面等於1的條件被<=5含在內,FIRST就表示前面插入了,後面不會再插入了。
insert first
when object_id = 1 then
into t1(object_name,object_id)
when object_id <=5 then                      
into t2(object_name,object_id)
select * from t;
commit;
select * from t1;
OBJECT_NAME                OBJECT_ID
--------------------------------- ---
ICOL$                              1
select * from t2;
OBJECT_NAME                OBJECT_ID
--------------------------------- ---
I_USER1                            2
CON$                               3
UNDO$                              4
C_COBJ#                            5
--insert all
insert all
when object_id = 1 then
into t1(object_name,object_id)
when object_id <=5 then                      
into t2(object_name,object_id)
select * from t;
commit;
SQL> select * from t1;
OBJECT_NAME                OBJECT_ID
--------------------------------- ---
ICOL$                              1
SQL> select * from t2;
OBJECT_NAME                OBJECT_ID
--------------------------------- ---
ICOL$                              1
I_USER1                            2
CON$                               3
UNDO$                              4
C_COBJ#                            5


行轉列插入

insert all還能夠實現行轉列插入:
select * from sales_source_data;
EMPLOYEE_ID    WEEK_ID  SALES_MON  SALES_TUE  SALES_WED SALES_THUR  SALES_FRI
----------- ---------- ---------- ---------- ---------- ---------- ----------
        176          6       2000       3000       4000       5000       6000
insert all
into sales_info values(employee_id,week_id,sales_mon)
into sales_info values(employee_id,week_id,sales_tue)
into sales_info values(employee_id,week_id,sales_wed)
into sales_info values(employee_id,week_id,sales_thur)
into sales_info values(employee_id,week_id,sales_fri)
select employee_id,week_id,sales_mon,sales_tue,
sales_wed,sales_thur,sales_fri
from sales_source_data;
select * from sales_info;
EMPLOYEE_ID       WEEK      SALES
----------- ---------- ----------
        176          6       2000
        176          6       3000
        176          6       4000
        176          6       5000
        176          6       6000

多表插入語句的限制條件

 1. 僅僅能對錶執行多表插入語句,不能對檢視或物化檢視執行;
 2. 不能對遠端表執行多表插入語句;
 3. 不能使用表集合表示式;
 4. 不能超過999個目標列;
 5. 在RAC環境中或目標表是索引組織表或目標表上建有BITMAP索引時,多表插入語句不能並行執行;
 6. 多表插入語句不支援執行計劃穩定性;
 7. 多表插入語句中的子查詢不能使用序列。





About Me

........................................................................................................................

● 本文作者:小麥苗,部分內容整理自網路,若有侵權請聯絡小麥苗刪除

● 本文在itpub、部落格園、CSDN和個人微 信公眾號( xiaomaimiaolhr)上有同步更新

● 本文itpub地址: http://blog.itpub.net/26736162

● 本文部落格園地址: http://www.cnblogs.com/lhrbest

● 本文CSDN地址: https://blog.csdn.net/lihuarongaini

● 本文pdf版、個人簡介及小麥苗雲盤地址: http://blog.itpub.net/26736162/viewspace-1624453/

● 資料庫筆試面試題庫及解答: http://blog.itpub.net/26736162/viewspace-2134706/

● DBA寶典今日頭條號地址: http://www.toutiao.com/c/user/6401772890/#mid=1564638659405826

........................................................................................................................

● QQ群號: 230161599 、618766405

● 微 信群:可加我微 信,我拉大家進群,非誠勿擾

● 聯絡我請加QQ好友 646634621 ,註明新增緣由

● 於 2019-09-01 06:00 ~ 2019-09-31 24:00 在西安完成

● 最新修改時間:2019-09-01 06:00 ~ 2019-09-31 24:00

● 文章內容來源於小麥苗的學習筆記,部分整理自網路,若有侵權或不當之處還請諒解

● 版權所有,歡迎分享本文,轉載請保留出處

........................................................................................................................

小麥苗的微店https://weidian.com/s/793741433?wfr=c&ifr=shopdetail

小麥苗出版的資料庫類叢書http://blog.itpub.net/26736162/viewspace-2142121/

小麥苗OCP、OCM、高可用網路班http://blog.itpub.net/26736162/viewspace-2148098/

小麥苗騰訊課堂主頁https://lhr.ke.qq.com/

........................................................................................................................

使用 微 信客戶端掃描下面的二維碼來關注小麥苗的微 信公眾號( xiaomaimiaolhr)及QQ群(DBA寶典)、新增小麥苗微 信, 學習最實用的資料庫技術。

........................................................................................................................

歡迎與我聯絡

 

 



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26736162/viewspace-2655888/,如需轉載,請註明出處,否則將追究法律責任。

相關文章