Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can INSERT [...] ON CONFLICT be used for foreign key violations?

Given

=> select * from referenced;
 referenced_id | name  
---------------+-------
             1 | one
             2 | two
             3 | three

and

=> select * from entries;
 entry_id | referenced_id |      name      
----------+---------------+------------------
        1 |             3 | references three

where referenced_id and entry_id are primary keys.

I want an insert statement for entries that skips insertion if either the entry_id already exists or the referenced item does not exist. The first is easily done:

INSERT INTO entries
VALUES (1, 2, 'references two')
ON CONFLICT (entry_id) DO NOTHING;

Is it possible to check for the existence of the foreign key here too?

like image 341
peterwimsey Avatar asked Mar 16 '16 14:03

peterwimsey


People also ask

What is the insert statement conflicted with the foreign key constraint?

You can get this error when you want to inset data into a table that has the Foreing Key. It means that there is no relevant record in the Primary table that Foreign Key is linked to. The record must first be added to the primary table.

Which constraints is applied on foreign key?

The FOREIGN KEY constraint is used to prevent actions that would destroy links between tables. A FOREIGN KEY is a field (or collection of fields) in one table, that refers to the PRIMARY KEY in another table.

What restriction on values does a foreign key enforce?

A foreign key is a column (or combination of columns) in a table whose values must match values of a column in some other table. FOREIGN KEY constraints enforce referential integrity, which essentially says that if column value A refers to column value B, then column value B must exist.

What is foreign key violation in SQL?

It causes violation only if the tuple in relation 1 is deleted which is referenced by foreign key from other tuples of table 2 in the database, if such deletion takes place then the values in the tuple of the foreign key in table 2 will become empty, which will eventually violate Referential Integrity constraint.


1 Answers

Yes, join your input rows to the referenced table, thereby removing rows without a match on the FK column:

INSERT INTO entries(entry_id, referenced_id, name)
SELECT val.entry_id, val.referenced_id, val.name
FROM  (
  VALUES (1, 2, 'references two')
         -- more?
  ) val (entry_id, referenced_id, name)
JOIN   referenced USING (referenced_id)  -- drop rows without matching FK
ON     CONFLICT (entry_id) DO NOTHING;   -- drop rows with duplicate id

The UPSERT itself (INSERT ... ON CONFLICT DO NOTHING) only reacts to unique violations. The manual:

ON CONFLICT can be used to specify an alternative action to raising a unique constraint or exclusion constraint violation error. (See ON CONFLICT Clause below.)

Since the VALUES expression is now not attached to an INSERT directly, column types are not derived from the target table. You may need to cast input values explicitly when operating with non-basic types. See:

  • Casting NULL type when updating multiple rows
like image 74
Erwin Brandstetter Avatar answered Oct 17 '22 19:10

Erwin Brandstetter