insert all
是指把 同一批
数据插入到 不同的表
中。insert into
语句效率要高。因为不论插入多少张表,主表(参考 dual)
只会被读取一次。假如,现在有个需求,把表
t
的中数据分别插入到t1、t2
,如果你不知道insert all
, 你可能会使用insert into
插入2
次,
在两次 insert
过程中, 有可能t
表的数据发生了改变,从而导致t1、t2
表得到的数据不一样,正确的写法是用insert all
(以下提供验证思路)
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;
两次 insert 时,若 主表 stu 发生改变,stu1、stu2 得到的数据可能不一致
使用 insert all 时,即使 主表 stu 发生改变,stu1、stu2 得到的数据也是一致的。
窗口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;
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;
/
执行前记录:(记录 删除 / 修改 原记录哦)
执行后记录:
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;
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;