Se você estiver inserindo apenas uma única linha por vez, poderá criar um ponto de salvamento antes da inserção e reversão para ele quando a inserção falhar (ou liberar quando a inserção for bem-sucedida).
INSERT ... ON CONFLICT DO NOTHING
que faz o que diz. Você pode também escreva ON CONFLICT DO UPDATE SET column = value...
, que converterá automaticamente sua inserção em uma atualização da linha com a qual você está em conflito (essa funcionalidade às vezes é chamada de "upsert").Isso não funciona porque o OP está lidando com uma chave estrangeira restrição em vez de um único restrição. Nesse caso, você pode usar mais facilmente o método de ponto de salvamento que descrevi anteriormente, mas para várias linhas pode ser tedioso. Se você precisar inserir várias linhas de uma vez, deve ter um desempenho razoável dividi-las em várias instruções de inserção, fornecidas você não está trabalhando no modo de confirmação automática , todas as inserções ocorrem em uma transação e você não está inserindo um número muito grande de linhas.
Às vezes, você realmente precisa de várias inserções em uma única instrução, porque a sobrecarga de ida e volta de falar com seu banco de dados mais o custo de ter pontos de salvamento em cada inserção é simplesmente muito alto. Neste caso, há uma série de abordagens imperfeitas. Provavelmente o menos ruim é construir uma consulta aninhada que seleciona seus dados e os une à outra tabela, algo assim:
INSERT INTO table_A (column_A, column_B, column_C)
SELECT A_rows.*
FROM VALUES (...) AS A_rows(column_A, column_B, column_C)
JOIN table_B ON A_rows.column_B = table_B.column_B;