Самая быстрая проверка, существует ли строка в PostgreSQL

У меня есть ряд строк, которые мне нужно вставить в таблицу, но эти вставки всегда выполняются партиями. Поэтому я хочу проверить, существует ли одна строка из пакета в таблице, потому что тогда я знаю, что все они были вставлены.

Таким образом, это не проверка первичного ключа, но это не должно иметь большого значения. Я бы хотел проверить только одну строку, поэтому count(*), вероятно, не очень хорошо, поэтому мне кажется что-то вроде exists.

Но так как я довольно новичок в PostgreSQL, я бы лучше спросил людей, которые знают.

Моя партия содержит строки со следующей структурой:

userid | rightid | remaining_count

Итак, если таблица содержит любые строки с предоставленным userid, это означает, что все они присутствуют там.

Ответ 1

Используйте ключевое слово EXISTS для возврата TRUE/FALSE:

select exists(select 1 from contact where id=12)

Ответ 2

Как насчет просто:

select 1 from tbl where userid = 123 limit 1;

где 123 - это идентификатор пакета, который вы собираетесь вставить.

Вышеприведенный запрос возвращает либо пустой набор, либо одну строку, в зависимости от наличия записей с указанным идентификатором пользователя.

Если это окажется слишком медленным, вы можете посмотреть на создание индекса на tbl.userid.

если даже одна строка из пакета существует в таблице, в этом случае я не нужно вставлять мои строки, потому что я точно знаю, что все они были вставлены.

Чтобы это оставалось верным, даже если ваша программа прервана в середине пакета, я рекомендую вам убедиться, что вы управляете транзакциями базы данных соответствующим образом (т.е. чтобы вся партия была вставлена ​​в рамках одной транзакции).

Ответ 3

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
    ;

сделает именно то, что вы хотите: либо он преуспеет, либо он терпит неудачу.

Ответ 4

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);

Ответ 5

как указал @MikeM.

select exists(select 1 from contact where id=12)

с индексом index на контакте обычно можно сократить затраты времени до 1 мс.

CREATE INDEX index_contact on contact(id);

Ответ 6

SELECT 1 FROM user_right where userid = ? LIMIT 1

Если ваш набор результатов содержит строку, вам не нужно вставлять ее. В противном случае вставьте свои записи.

Ответ 7

Если вы думаете об эффективности, возможно, вы можете использовать "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;