Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4183954
  • 博文数量: 240
  • 博客积分: 11504
  • 博客等级: 上将
  • 技术积分: 4277
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-28 14:24
文章分类

全部博文(240)

分类: Mysql/postgreSQL

2014-01-16 15:55:16

对MySQL熟悉的人可能都知道,MySQL 有一个“insert ignore" 语法来忽略已经存在的记录。 PostgreSQL暂时不提供这样的语法,但是可以用其他方法来代替。


以下为本次演示的样例表结构以及数据。


点击(此处)折叠或打开

  1. t_girl=# \d insert_ignore
  2.            Table "ytt.insert_ignore"
  3.   Column | Type | Modifiers
  4. ----------+------------------------+-----------
  5.  id | integer | not null
  6.  log_time | time without time zone |
  7. Indexes:
  8.     "insert_ignore_pkey" PRIMARY KEY, btree (id)


  9. t_girl=# select * from insert_ignore;
  10.  id | log_time
  11. ----+----------------
  12.   1 | 14:44:12.37185
  13. (1 row)



我来演示下几种代替方法。


第一种方法, 用自带的规则(RULE)来实现。


点击(此处)折叠或打开

  1. t_girl=# create rule r_insert_ignore as on insert to insert_ignore where exists (select 1 from insert_ignore where id = new.id) do instead nothing;
  2. CREATE RULE


  3. 这时,我们插入两条记录,其中一条的主键值已经存在,直接忽略掉。 实际插入的记录数为1.
  4. t_girl=# insert into insert_ignore values(1,current_time),(2,current_time);
  5. INSERT 0 1
  6. t_girl=# select * from insert_ignore;
  7.  id | log_time
  8. ----+-----------------
  9.   1 | 14:44:12.37185
  10.   2 | 14:48:22.222848
  11. (2 rows)



第二种方法, 建立一个返回NULL的触发器函数。 那么函数体如下:


点击(此处)折叠或打开

  1. t_girl=# create or replace function sp_insert_ignore() returns trigger as
  2.  $ytt$
  3.  begin
  4.    perform 1 from insert_ignore where id = new.id;
  5.    if found then
  6.      return null;
  7.   end if;
  8.   return new;
  9. end;
  10. $ytt$ language 'plpgsql';
  11. CREATE FUNCTION


点击(此处)折叠或打开

  1. 对应的触发器如下:
  2. t_girl=# create trigger tr_ib_insert_ignore before insert on insert_ignore for each row execute procedure sp_insert_ignore();
  3. CREATE TRIGGER


  4. 继续插入两条记录。
  5. t_girl=# insert into insert_ignore values (3,current_time),(2,current_time);
  6. INSERT 0 1
  7. t_girl=# select * from insert_ignore;
  8.  id | log_time
  9. ----+-----------------
  10.   1 | 14:44:12.37185
  11.   2 | 14:48:22.222848
  12.   3 | 15:05:33.198847
  13. (3 rows)


  14. OK。目的达到了。




第三种方法,用WITH来实现。


点击(此处)折叠或打开

  1. t_girl=# insert into insert_ignore
  2. with ytt_test(f1,f2) as (
  3. values(6,current_time),(3,current_time)
  4. )
  5. select a.* from ytt_test as a where a.f1 not in (select id from insert_ignore as b);
  6. INSERT 0 1
  7. 查看记录,插入了一条ID为6的记录,忽略了ID为3的记录。
  8. t_girl=# select * from insert_ignore;
  9.  id | log_time
  10. ----+-----------------
  11.   1 | 14:44:12.37185
  12.   2 | 14:48:22.222848
  13.   3 | 15:05:33.198847
  14.   6 | 15:15:52.297802
  15. (4 rows)



第四种,用存储过程来代替INSERT处理。


点击(此处)折叠或打开

  1. t_girl=# create or replace function sp_insert_ignore (
  2. IN f_id int,
  3. IN f_log_time time without time zone
  4. ) returns void as
  5. $ytt$
  6. begin
  7.   insert into insert_ignore values (f_id,f_log_time);
  8.   exception when unique_violation then
  9.     raise notice 'Duplicated Key Error on ID:%',f_id;
  10.     return;
  11. end;
  12. $ytt$ language plpgsql;


  13. 第一次调用,抛出了错误。
  14. t_girl=# select sp_insert_ignore(1,'14:22:35'::time);
  15. NOTICE: Duplicated Key Error on ID:1
  16.  sp_insert_ignore
  17. ------------------
  18.  
  19. (1 row)


  20. 第二次正常插入。
  21. t_girl=# select sp_insert_ignore(8,'14:22:35'::time);
  22.  sp_insert_ignore
  23. ------------------
  24.  
  25. (1 row)


  26. t_girl=# select * from insert_ignore;
  27.  id | log_time
  28. ----+-----------------
  29.   1 | 14:44:12.37185
  30.   2 | 14:48:22.222848
  31.   3 | 15:05:33.198847
  32.   6 | 15:15:52.297802
  33.   8 | 14:22:35
  34. (5 rows)


  35. t_girl=#
  36. OK,目的也达到了。

阅读(118039) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~