我有一堆需要插入到表中的行,但这些插入总是分批完成的。所以我想检查表中是否存在批处理中的一行,因为那时我知道它们都被插入了。
所以它不是一个主键检查,但不应该太重要。我只想检查单行,所以 count(*)
可能不好,所以我猜它类似于 exists
。
但是由于我对 PostgreSQL 还很陌生,所以我宁愿问知道的人。
我的批次包含具有以下结构的行:
userid | rightid | remaining_count
因此,如果表包含任何带有提供的 userid
的行,则意味着它们都存在于那里。
简单地说:
select 1 from tbl where userid = 123 limit 1;
其中 123
是您要插入的批次的用户 ID。
上述查询将返回空集或单行,具体取决于是否存在具有给定用户 ID 的记录。
如果结果太慢,您可以考虑在 tbl.userid
上创建索引。
如果表中甚至存在批处理中的单行,在这种情况下,我不必插入我的行,因为我确定它们都已插入。
即使您的程序在批处理中被中断,为了保持这一点,我建议您确保适当地管理数据库事务(即整个批处理插入到单个事务中)。
COUNT
作用于最多有 1 行的嵌套 SELECT
(因为 LIMIT
在子查询中)。
INSERT INTO target( userid, rightid, count )
SELECT userid, rightid, count
FROM batch
WHERE NOT EXISTS (
SELECT * FROM target t2, batch b2
WHERE t2.userid = b2.userid
-- ... other keyfields ...
)
;
顺便说一句:如果您希望整个批次在重复的情况下失败,那么(给定主键约束)
INSERT INTO target( userid, rightid, count )
SELECT userid, rightid, count
FROM batch
;
将完全按照您的意愿行事:要么成功,要么失败。
正如@MikeM 指出的那样。
select exists(select 1 from contact where id=12)
使用 index on contact,通常可以将时间成本降低到 1 ms。
CREATE INDEX index_contact on contact(id);
如果你考虑一下性能,也许你可以在一个函数中使用“PERFORM”,就像这样:
PERFORM 1 FROM skytf.test_2 WHERE id=i LIMIT 1;
IF FOUND THEN
RAISE NOTICE ' found record id=%', i;
ELSE
RAISE NOTICE ' not found record id=%', i;
END IF;
SELECT 1 FROM user_right where userid = ? LIMIT 1
如果您的结果集包含一行,那么您不必插入。否则插入您的记录。
select true from tablename where condition limit 1;
我相信这是 postgres 用于检查外键的查询。
在您的情况下,您也可以一次性完成:
insert into yourtable select $userid, $rightid, $count where not (select true from yourtable where userid = $userid limit 1);
select exists(select 1 from contact where id=12) AS "exists"
exists
或limit 1
时,我的性能下降很大,因为 Postgres 使用 Seq Scan 而不是 Index Scan。analyze
也无济于事。limit 1
会帮助还是减慢查询?