Oracle insert all 详解

文章目录

  • 1、概述
    • 1.1 场景
    • 1.2 数据准备
    • 1.3 思维导图
  • 2、数据一致性(场景验证)
    • 2.1 结论1:insert 数据不一致
    • 2.2 结论2:insert all 数据一致
  • 3、insert 两种形式
    • 3.1 insert first
    • 3.2 insert all

1、概述

1.1 场景

  • Oracle 中insert all 是指把 同一批 数据插入到 不同的表 中。
  • 这方式要比写多个 insert into 语句效率要高。因为不论插入多少张表,主表(参考 dual) 只会被读取一次。

假如,现在有个需求,把表 t 的中数据分别插入到 t1、t2,如果你不知道 insert all, 你可能会使用 insert into 插入 2 次,
两次 insert 过程中, 有可能 t 表的数据发生了改变,从而导致 t1、t2 表得到的数据不一样,正确的写法是用 insert all(以下提供验证思路)

1.2 数据准备

CREATE TABLE stu(
   ID   NUMBER(3),
   NAME VARCHAR2(30),
   sex  VARCHAR2(2)
);

INSERT INTO stu(ID, NAME, sex) VALUES(1, '小游子', '女');
INSERT INTO stu(ID, NAME, sex) VALUES(2, '小优子', '男');
INSERT INTO stu(ID, NAME, sex) VALUES(3, '小倩子', '女');

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

1.3 思维导图

Oracle insert all 详解_第1张图片

2、数据一致性(场景验证)

  • 结论:
    • 1:两次 insert 时,若 主表 stu 发生改变,stu1、stu2 得到的数据可能不一致
    • 2:使用 insert all 时,即使 主表 stu 发生改变,stu1、stu2 得到的数据也是一致的。
  • 模拟:将表 stu 中的数据分别插入 stu1、stu2
  • 分三个窗口
    • 窗口1:将 stu 数据插入 stu1(模拟时长 30 s)
    • 窗口2:将 stu 数据插入 stu2(模拟时长 30 s)
    • 窗口3:此时更新 stu 记录,使之影响 stu1、stu2(上述模拟时长内)

2.1 结论1:insert 数据不一致

窗口1:将 stu 数据插入 stu1(模拟时长 30 s)
更新 id = 2 的记录时,等待

DECLARE
BEGIN
   FOR i IN 1 .. 3 LOOP
   
      IF i = 2 THEN
         dbms_lock.sleep(30); -- 模拟执行时长:30 秒
      END IF;
   
      INSERT INTO stu1
         (id, NAME, sex)
         SELECT t.id, t.name, t.sex FROM stu t WHERE t.id = i;
      COMMIT;
      
   END LOOP;

END;
/

窗口2:将 stu 数据插入 stu2(模拟时长 30 s)
更新 id = 3 的记录时,等待

DECLARE
BEGIN
   FOR i IN 1 .. 3 LOOP
   
      IF i = 3 THEN
         dbms_lock.sleep(30); -- 模拟执行时长:30 秒
      END IF;
   
      INSERT INTO stu2
         (id, NAME, sex)
         SELECT t.id, t.name, t.sex FROM stu t WHERE t.id = i;
      COMMIT;
      
   END LOOP;

END;
/

窗口3:此时更新 stu 记录,使之影响 stu1、stu2(上述模拟时长内)

UPDATE stu t SET t.name = 'update_2', t.sex = '22' WHERE t.id = 2;
COMMIT;

执行前记录:

SELECT 'stu' table_name, t.* FROM stu t 
UNION ALL
SELECT 'stu1' table_name, t1.* FROM stu1 t1
UNION ALL
SELECT 'stu2' table_name, t2.* FROM stu2 t2;

在这里插入图片描述

执行后记录:
Oracle insert all 详解_第2张图片

2.2 结论2:insert all 数据一致

DECLARE
BEGIN
   FOR i IN 1 .. 3 LOOP
   
      IF i = 2 THEN
         dbms_lock.sleep(30); -- 模拟执行时长:30 秒
      END IF;
   
      INSERT ALL 
         INTO stu1(id, NAME, sex) 
         INTO stu2(id, NAME, sex)
      SELECT t.id, t.name, t.sex FROM stu t WHERE t.id = i; 
      COMMIT;
   
   END LOOP;

END;
/

执行前记录:(记录 删除 / 修改 原记录哦)
在这里插入图片描述
执行后记录:
Oracle insert all 详解_第3张图片

3、insert 两种形式

3.1 insert first

  • 仅对 第一个 when 进行匹配(第一次匹配成功后,break)
INSERT FIRST
  WHEN t.id >= 2 THEN
    INTO stu1(ID, NAME, sex)
  WHEN t.id >= 3 THEN
    INTO stu2(ID, NAME, sex) 
SELECT t.id, t.name, t.sex FROM stu t;

查询:

SELECT 'stu' table_name, t.* FROM stu t 
UNION ALL
SELECT 'stu1' table_name, t1.* FROM stu1 t1
UNION ALL
SELECT 'stu2' table_name, t2.* FROM stu2 t2;

执行前记录:
在这里插入图片描述

执行后记录:
Oracle insert all 详解_第4张图片

3.2 insert all

  • 对每个 when 都进行匹配(执行完成后,break)
INSERT ALL
  WHEN id >= 2 THEN
    INTO stu1(ID, NAME, sex)
  WHEN id >= 3 THEN
    INTO stu2(ID, NAME, sex) 
SELECT t.id, t.name, t.sex FROM stu t;

执行前记录:
在这里插入图片描述
执行后记录:
Oracle insert all 详解_第5张图片

你可能感兴趣的:(Oracle insert all 详解)