Eu tenho um monte de linhas que preciso inserir na tabela, mas essas inserções são sempre feitas em lotes. Então, eu quero verificar se existe uma única linha do lote na tabela, porque sei que todas foram inseridas.
Portanto, não é uma verificação de chave primária, mas não deve importar muito. Eu gostaria de verificar apenas uma linha, então count(*)
provavelmente não é bom, então é algo que exists
eu acho.
Mas como sou bastante novo no PostgreSQL, prefiro perguntar às pessoas que o conhecem.
Meu lote contém linhas com a seguinte estrutura:
userid | rightid | remaining_count
Portanto, se a tabela contiver alguma linha com, userid
isso significa que todas elas estão presentes lá.
sql
postgresql
Valentin Kuzub
fonte
fonte
Respostas:
Use a palavra-chave EXISTS para retornar VERDADEIRO / FALSO:
fonte
select exists(select 1 from contact where id=12) AS "exists"
exists
oulimit 1
tenho forte queda de desempenho, porque o Postgres usa a Seq Scan em vez da Index Scan. Eanalyze
não ajuda.Que tal simplesmente:
onde
123
está o ID do usuário do lote que você está prestes a inserir.A consulta acima retornará um conjunto vazio ou uma única linha, dependendo se há registros com o ID do usuário fornecido.
Se isso for muito lento, você pode criar um índice
tbl.userid
.Para que isso permaneça verdadeiro, mesmo que seu programa seja interrompido no meio do lote, eu recomendo que você gerencie as transações do banco de dados de maneira apropriada (ou seja, que todo o lote seja inserido em uma única transação).
fonte
COUNT
atua sobre uma aninhadaSELECT
que tem, no máximo, 1 linha (porque oLIMIT
é na subconsulta).BTW: se você deseja que todo o lote falhe em caso de duplicação, então (dada uma restrição de chave primária)
fará exatamente o que você deseja: ou é bem-sucedido ou falha.
fonte
Eu acredito que esta é a consulta que o postgres usa para verificar chaves estrangeiras.
No seu caso, você também pode fazer isso de uma só vez:
fonte
como o @MikeM apontou.
com o índice no contato, geralmente pode reduzir o custo do tempo para 1 ms.
fonte
Se o seu conjunto de resultados contiver uma linha, você não precisará inserir. Caso contrário, insira seus registros.
fonte
Se você pensa sobre o desempenho, pode ser que você possa usar "PERFORM" em uma função como esta:
fonte
Gostaria de propor outro pensamento para abordar especificamente sua frase: "Quero verificar se existe uma única linha do lote na tabela, porque sei que todas foram inseridas ".
Você está tornando as coisas eficientes, inserindo "lotes", mas depois verificando a existência, um registro de cada vez? Isso parece contra-intuitivo para mim. Então, quando você diz " inserções sempre são feitas em lotes ", entendo que você esteja inserindo vários registros com uma instrução de inserção . Você precisa perceber que o Postgres é compatível com ACID. Se você estiver inserindo vários registros (um lote de dados) com uma instrução de inserção , não será necessário verificar se alguns foram inseridos ou não. A declaração é aprovada ou falhará. Todos os registros serão inseridos ou nenhum.
Por outro lado, se o seu código C # estiver simplesmente fazendo um conjunto de instruções de inserção separadas, por exemplo, em um loop, e em sua mente, este é um "lote" .. então você não deve descrevê-lo como " inserções são sempre feitas em lotes ". O fato de que você espera que parte do que você chama de "lote" possa não ser realmente inserido e, portanto, sinta a necessidade de uma verificação, sugere fortemente que esse é o caso, caso em que você tem um problema mais fundamental. Você precisa alterar seu paradigma para realmente inserir vários registros com uma inserção e deixar de verificar se os registros individuais o fizeram.
Considere este exemplo:
Na verdade, esse é o paradigma de qualquer banco de dados compatível com ACID. Não apenas o Postgresql. Em outras palavras, você estará melhor se corrigir o conceito de "lote" e evitar a necessidade de fazer verificações linha por linha em primeiro lugar.
fonte