2012-02-17 88 views
0

背景:这是一个Ruby on Rails web应用程序。我有一个后台工作,从Facebook下载最近的帖子并将其插入到数据库中。我使用手动编码的SQL来提高性能。 RDBMS是PostgreSQL(在Heroku上)。此SQL查询如何可能将重复值插入到数据库中?

该表被称为“帖子”。我对posts.uidposts.contact_id的组合有独特的索引。在SQL中,我使用WHERE条件过滤掉uid - contact_id组合,其已在该表中,但即便如此,我收到以下错误:

ActiveRecord::RecordNotUnique: PGError: ERROR: duplicate key value violates unique constraint "index_posts_on_uid_and_contact_id"

事不宜迟,这里是(动态)SQL:

INSERT INTO posts 
(message,contact_id,date,uid,created_at,updated_at,source,is_event) 
SELECT 
    t.msg, 
    contacts.id, 
    t.date, 
    t.uid, 
    CURRENT_TIMESTAMP, 
    CURRENT_TIMESTAMP,'facebook', 
    FALSE 
FROM contacts, 
(VALUES #{posts.map { |post| "(E'#{post['message'].escape_singles}','# 
{post['uid']}',DATE '#{format_date(post['time'])}',#{post['status_id']})" }.join(", ")}) AS  
t (msg,fb_id,date,uid) 
WHERE contacts.fb_id = t.fb_id 
AND (NOT EXISTS (
      SELECT * FROM posts 
      WHERE posts.uid = t.uid 
      AND posts.contact_id = contacts.id)); 

NOT EXISTS条件不应该防止这种情况发生吗?

+3

如果您只是运行select子句中的所有内容,您的数据是什么样的?那是返回重复数据吗? – 2012-02-17 15:23:00

+0

这将需要不到2分钟的时间来测试,因为您已经拥有数据库并且查询已准备就绪。你真的在问什么?你测试过了吗?它不工作吗? – kba 2012-02-17 15:23:50

+0

Doug R和BD,很好的建议。我会尝试。 KristianAntonsen,我不确定你是否阅读了整个问题,但是,我已经测试过了,并且我得到了“违反了唯一约束”的错误。我看不出有可能发生这种情况(但其他两位评论者可能已经指出了这一点)。 – 2012-02-17 15:31:18

回答

2

你的选择查询返回重复的行。

1

检查空值。

我认为唯一索引"index_posts_on_uid_and_contact_id"不是PK,所以它会接受空值。如果在

SELECT * FROM posts 
      WHERE posts.uid = t.uid 
      AND posts.contact_id = contacts.id 

查询中的一个字段为空的存在会返回假的,复制的数据可以插入。我想做select 1而不是select *。我认为其更好

我会做

WHERE (contacts.fb_id = t.fb_id) and (t.uid is not null) and (contacts.id is not null) 
+0

当在像这样的子查询中使用'select 1'比'select *'更快吗? RDBMS的查询优化器不会看到子查询在EXISTS子句中使用并优化吗? – 2012-02-17 15:43:03

+0

我不知道!这当然是有意义的,但当然,只是为了保存,我总是在选择“存在”时选择1。仅供参考,这就是为什么我说“我认为”,因为我不确定 – Diego 2012-02-17 15:48:43

+0

+1在'select 1'上的提示。但是,如果他真的发布了他的答案,那么接受去@DougR。 – 2012-02-17 15:56:24

相关问题