背景:这适用于Ruby on Rails Web应用程序。我有一份后台工作,从Facebook下载最近的帖子并将它们插入数据库。我正在使用手工编写的SQL来提高性能。 RDBMS是PostgreSQL(在Heroku上)。
该表称为“帖子”。我对posts.uid
和posts.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条件不应该阻止这种情况发生吗?
答案 0 :(得分:2)
您的选择查询将返回重复的行。
答案 1 :(得分:1)
检查空值。
我假设唯一索引"index_posts_on_uid_and_contact_id"
不是PK,因此它将接受空值。
SELECT * FROM posts
WHERE posts.uid = t.uid
AND posts.contact_id = contacts.id
query为null,exists将返回false,并且可能会插入重复的数据。
另外,我会select 1
代替select *
。我认为它更好
我愿意
WHERE (contacts.fb_id = t.fb_id) and (t.uid is not null) and (contacts.id is not null)