Ответ 1
Используйте ключевое слово EXISTS для возврата TRUE/FALSE:
select exists(select 1 from contact where id=12)
У меня есть ряд строк, которые мне нужно вставить в таблицу, но эти вставки всегда выполняются партиями. Поэтому я хочу проверить, существует ли одна строка из пакета в таблице, потому что тогда я знаю, что все они были вставлены.
Таким образом, это не проверка первичного ключа, но это не должно иметь большого значения. Я бы хотел проверить только одну строку, поэтому count(*)
, вероятно, не очень хорошо, поэтому мне кажется что-то вроде exists
.
Но так как я довольно новичок в PostgreSQL, я бы лучше спросил людей, которые знают.
Моя партия содержит строки со следующей структурой:
userid | rightid | remaining_count
Итак, если таблица содержит любые строки с предоставленным userid
, это означает, что все они присутствуют там.
Используйте ключевое слово EXISTS для возврата TRUE/FALSE:
select exists(select 1 from contact where id=12)
Как насчет просто:
select 1 from tbl where userid = 123 limit 1;
где 123
- это идентификатор пакета, который вы собираетесь вставить.
Вышеприведенный запрос возвращает либо пустой набор, либо одну строку, в зависимости от наличия записей с указанным идентификатором пользователя.
Если это окажется слишком медленным, вы можете посмотреть на создание индекса на tbl.userid
.
если даже одна строка из пакета существует в таблице, в этом случае я не нужно вставлять мои строки, потому что я точно знаю, что все они были вставлены.
Чтобы это оставалось верным, даже если ваша программа прервана в середине пакета, я рекомендую вам убедиться, что вы управляете транзакциями базы данных соответствующим образом (т.е. чтобы вся партия была вставлена в рамках одной транзакции).
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
;
сделает именно то, что вы хотите: либо он преуспеет, либо он терпит неудачу.
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);
как указал @MikeM.
select exists(select 1 from contact where id=12)
с индексом index на контакте обычно можно сократить затраты времени до 1 мс.
CREATE INDEX index_contact on contact(id);
SELECT 1 FROM user_right where userid = ? LIMIT 1
Если ваш набор результатов содержит строку, вам не нужно вставлять ее. В противном случае вставьте свои записи.
Если вы думаете об эффективности, возможно, вы можете использовать "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;