我有一堆行需要插入到表中,但这些插入总是分批完成。所以我想检查表中是否存在批处理中的一行,因为我知道它们都已插入。
所以它不是主键检查,但不应该太重要。我想只检查单行,因此count(*)
可能不好,所以我猜是exists
。
但是因为我对PostgreSQL很新,所以我宁愿问那些知道的人。
我的批处理包含具有以下结构的行:
userid | rightid | remaining_count
因此,如果表包含提供userid
的任何行,则表示它们都存在于那里。
答案 0 :(得分:247)
使用EXISTS关键字返回TRUE / FALSE:
select exists(select 1 from contact where id=12)
答案 1 :(得分:30)
简单地说:
select 1 from tbl where userid = 123 limit 1;
其中123
是您要插入的批次的用户ID。
以上查询将返回空集或单行,具体取决于是否存在具有给定用户标识的记录。
如果结果太慢,您可以考虑在tbl.userid
上创建索引。
如果表中存在批处理中的单行,那么我就是这样 不必插入我的行,因为我知道他们都是 插入
即使您的程序在批处理中被中断,为了保持这一点,我建议您确保适当地管理数据库事务(即整个批处理在单个事务中插入)。
答案 2 :(得分:9)
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 ...
)
;
BTW:如果你希望整批失败,如果有重复,那么(给定主键约束)
INSERT INTO target( userid, rightid, count )
SELECT userid, rightid, count
FROM batch
;
将完全按照您的意愿行事:要么成功要么失败。
答案 3 :(得分: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);
答案 4 :(得分:1)
@MikeM指出。
select exists(select 1 from contact where id=12)
与索引保持联系,通常可以将时间成本降低到1毫秒。
CREATE INDEX index_contact on contact(id);
答案 5 :(得分:0)
SELECT 1 FROM user_right where userid = ? LIMIT 1
如果结果集包含一行,则不必插入。否则插入你的记录。
答案 6 :(得分:0)
如果您考虑性能,也许您可以在这样的函数中使用“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;
答案 7 :(得分:0)
经验法则
选择存在( 从xx中选择true,其中xx )" 1 + 1加起来是2&#34 ;;
答案 8 :(得分:0)
我想提出另一种想法来专门解决您的句子:“因此,我想检查表中是否存在该批次中的一行,因为那么我知道它们都是 插入。”
您通过插入“批”来提高效率,但是然后一次进行一次存在性检查?这对我来说似乎很直觉。因此,当您说“ 插入总是成批完成”时,我想您是说您要使用一个插入语句插入多个记录。您需要认识到Postgres符合ACID。如果您要通过一条插入语句插入多条记录(一批数据),则无需检查是否已插入某些记录。该语句要么通过,要么失败。将插入所有记录或不插入所有记录。
另一方面,如果您的C#代码只是在循环中简单地“设置”单独的插入语句,并且在您的脑海中,这是一个“批处理” ..那么您实际上不应描述因为“插入总是分批完成”。您期望实际上可能未插入“批处理”部分的事实,因此感到需要检查,这一事实强烈表明了这种情况,在这种情况下,您有一个更根本的问题。您需要更改范例,以便实际上一次插入多个记录,并放弃检查是否有单个记录。
考虑以下示例:
CREATE TABLE temp_test (
id SERIAL PRIMARY KEY,
sometext TEXT,
userid INT,
somethingtomakeitfail INT unique
)
-- insert a batch of 3 rows
;;
INSERT INTO temp_test (sometext, userid, somethingtomakeitfail) VALUES
('foo', 1, 1),
('bar', 2, 2),
('baz', 3, 3)
;;
-- inspect the data of what we inserted
SELECT * FROM temp_test
;;
-- this entire statement will fail .. no need to check which one made it
INSERT INTO temp_test (sometext, userid, somethingtomakeitfail) VALUES
('foo', 2, 4),
('bar', 2, 5),
('baz', 3, 3) -- <<--(deliberately simulate a failure)
;;
-- check it ... everything is the same from the last successful insert ..
-- no need to check which records from the 2nd insert may have made it in
SELECT * FROM temp_test
这实际上是任何符合ACID的数据库的范式..不仅仅是Postgresql。换句话说,如果您解决了“批处理”的概念,而不必首先进行逐行检查,那么情况会更好。