Search code examples
postgresqlelixirecto

When to use "nothing" or "restrict" for "on_delete" with Ecto?


I've read this question but I don't understand this part:

the essential difference between these two choices is that [:nothing] allows the check to be deferred until later in the transaction, whereas [:restrict] does not.

When should I know I need to defer or not the check since I know I need to check anyway?


Solution

  • It depends on the DB you are using.

    If you are using MySQL they're exactly the same because the checks are always done at the start of transaction.

    NO ACTION: A keyword from standard SQL. In MySQL, equivalent to RESTRICT. The MySQL Server rejects the delete or update operation for the parent table if there is a related foreign key value in the referenced table. Some database systems have deferred checks, and NO ACTION is a deferred check. In MySQL, foreign key constraints are checked immediately, so NO ACTION is the same as RESTRICT. Source: https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html

    If we look at the Postgres documentation we see that there is a difference.

    Restricting and cascading deletes are the two most common options. RESTRICT prevents deletion of a referenced row. NO ACTION means that if any referencing rows still exist when the constraint is checked, an error is raised; this is the default behavior if you do not specify anything. (The essential difference between these two choices is that NO ACTION allows the check to be deferred until later in the transaction, whereas RESTRICT does not.) Source: https://www.postgresql.org/docs/9.5/ddl-constraints.html

    I was also curious as to why you might want to pick one over the other and the answer seems to be performance. Look at this mail thread:

    As for why you might want a deferred check, the only practical use I can think of is to delete a referenced row in the master table, then insert a replacement row with the same key, before ending the transaction. In principle you could do that as a single UPDATE, but it might be that your application logic makes it awkward to do so. Source: https://www.postgresql.org/message-id/4271.1233022978%40sss.pgh.pa.us