Se stai inserendo una sola riga alla volta, puoi creare un punto di salvataggio prima dell'inserto e rollback ad esso quando l'inserimento non riesce (o rilascialo quando l'inserimento riesce).
Per Postgres 9.5 o versioni successive, puoi utilizzare INSERT ... ON CONFLICT DO NOTHING
che fa quello che dice. Puoi anche scrivi ON CONFLICT DO UPDATE SET column = value...
, che converte automaticamente il tuo inserto in un aggiornamento della riga con cui sei in conflitto (questa funzionalità è talvolta chiamata "upsert").
Questo non funziona perché OP ha a che fare con una chiave esterna vincolo piuttosto che un unico vincolo. In tal caso, puoi utilizzare più facilmente il metodo savepoint che ho descritto in precedenza, ma per più righe potrebbe risultare noioso. Se è necessario inserire più righe contemporaneamente, dovrebbe essere ragionevolmente efficace suddividerle in più istruzioni di inserimento, a condizione non lavora in modalità autocommit , tutti gli inserimenti si verificano in un'unica transazione e non stai inserendo un numero molto elevato di righe.
A volte, hai davvero bisogno di più inserti in una singola istruzione, perché il sovraccarico di andata e ritorno per parlare con il tuo database più il costo di avere punti di salvataggio su ogni inserto è semplicemente troppo alto. In questo caso, ci sono una serie di approcci imperfetti. Probabilmente il meno cattivo è creare una query nidificata che seleziona i tuoi dati e li unisce all'altra tabella, qualcosa del genere:
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;