往期回顾:
-- 设置显示参数 set pagesize 3000; set linesize 300; set trim on -- 创建测试表 drop table t purge; create table t(msg_id number(15), user_id number(9), msg varchar2(4000)); -- 创建行级触发器,在插入前检查msg_id是否存在 create trigger tri_t before insert on t for each row declare v_cnt number(1); begin select count(*) into v_cnt from t where msg_id = :new.msg_id and rownum = 1; end tri_t; /
-- 启用触发器 SQL> set timing on SQL> alter trigger tri_t enable; 触发器已更改 已用时间: 00: 00: 00.03 -- 执行批量插入(3万条记录) SQL> declare 2 v_msgid number(15); 3 v_usrid number(9); 4 begin 5 dbms_random.seed(1000000000); 6 for i in 1 .. 30000 loop 7 v_usrid := dbms_random.value; 8 v_msgid := i; 9 execute immediate 'insert into t (msg_id, user_id, msg) values (:p1, :p2,:p3)' 10 using v_msgid, v_usrid, 'msg_' || i; 11 end loop; 12 end; 13 / PL/SQL 过程已成功完成。 已用时间: 00: 00: 46.62
-- 清空表 SQL> truncate table t; 表被截断。 已用时间: 00: 00: 00.35 -- 禁用触发器 SQL> alter trigger tri_t disable; 触发器已更改 已用时间: 00: 00: 00.00 -- 执行相同的批量插入 SQL> declare 2 v_msgid number(15); 3 v_usrid number(9); 4 begin 5 dbms_random.seed(1000000000); 6 for i in 1 .. 30000 loop 7 v_usrid := dbms_random.value; 8 v_msgid := i; 9 execute immediate 'insert into t (msg_id, user_id, msg) values (:p1, :p2, :p3)' 10 using v_msgid, v_usrid, 'msg_' || i; 11 end loop; 12 end; 13 / PL/SQL 过程已成功完成。 已用时间: 00: 00: 01.81
-- 批量插入前先检查重复值 declare v_msgid number(15); v_usrid number(9); v_duplicate_exists boolean := false; begin -- 一次性检查重复值 select case when count(*) > 0 then true else false end into v_duplicate_exists from (select distinct i from (select level i from dual connect by level <= 30000)) where exists (select 1 from t where msg_id = i); if v_duplicate_exists then raise_application_error(-20001, '存在重复的MSG_ID值'); end if; -- 确认无重复后批量插入 dbms_random.seed(1000000000); for i in 1 .. 30000 loop v_usrid := dbms_random.value; v_msgid := i; execute immediate 'insert into t (msg_id, user_id, msg) values (:p1, :p2,:p3)' using v_msgid, v_usrid, 'msg_' || i; end loop; end; /
-- 改为语句级触发器并使用批量处理
create or replace trigger tri_t_statement
after insert on t
declare
-- 用于临时存储需要处理的数据
cursor c_inserted is
select msg_id from t where msg_id not in
(select msg_id from t group by msg_id having count(*) = 1);
begin
-- 一次性处理所有重复数据
for r in c_inserted loop
-- 处理逻辑
dbms_output.put_line('检测到重复的MSG_ID: ' || r.msg_id);
end loop;
end;
/
-- 使用唯一约束替代唯一性检查触发器alter table t add constraint uk_t_msg_id unique (msg_id);
-- 创建独立存储过程
create or replace procedure validate_msg_ids as
v_duplicates number;
begin
-- 检查是否存在重复MSG_ID
select count(*)
into v_duplicates
from t
group by msg_id
having count(*) > 1
fetch first row only;
if v_duplicates > 0 then
dbms_output.put_line('检测到重复的MSG_ID');
-- 处理重复记录的逻辑
end if;
end;
/
-- 在数据加载后调用一次
declare
v_msgid number(15);
v_usrid number(9);
begin
-- 批量插入
dbms_random.seed(1000000000);
for i in 1 .. 30000 loop
v_usrid := dbms_random.value;
v_msgid := i;
execute immediate 'insert into t (msg_id, user_id, msg) values (:p1, :p2,:p3)'
using v_msgid, v_usrid, 'msg_' || i;
end loop;
-- 数据加载完成后调用一次验证
validate_msg_ids;
end;
/
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/9091385/viewspace-3083129/ ,如需转载,请注明出处,否则将追究法律责任。