MySQL RESTRICT and NO ACTION - mysql

What's the difference in a MySQL FK between RESTRICT and NO ACTION? From the doc they seem exactly the same. Is this the case? If so, why have both?

From MySQL Documentation: https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html
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.

It is to comply with standard SQL syntax. Like the manual says: (emphasis mine)
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.

They are identical in MySQL.
In the SQL 2003 standard there are 5 different referential actions:
CASCADE
RESTRICT
NO ACTION
SET NULL
SET DEFAULT
The difference between NO ACTION and RESTRICT is that according to the standard, NO ACTION is deferred while RESTRICT acts immediately.

Related

Why Django CheckConstraint doesn't works on MySQL

When I create one class with constraint like below:
constraints = [
models.CheckConstraint(
check=models.Q('plan' == 1),
name="custom_constraint"
)
]
I receive the message:
(models.W027) MySQL does not support check constraints.
HINT: A constraint won't be created. Silence this warning if you don't care about it.
Why Django CheckConstraints works with PostgreSQL and not with MySQL?
As per MySQL documentation, the CHECK constraints are ignored by the MySQL database prior to 8.0.16:
Prior to MySQL 8.0.16, CREATE TABLE permits only the following limited version of table CHECK constraint syntax, which is parsed
and ignored**:
CHECK (expr)
As of MySQL 8.0.16, CREATE TABLE permits the core features of table and column CHECK constraints, for all storage engines.
CREATE TABLE permits the following CHECK constraint syntax, for
both table constraints and column constraints:
[CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]
So before 8.0.16, the CHECK constraint was indeed parsed, but the database engine ignored it, and thus data could violate the constraints.
Some specific constraints like NOT NULL, UNIQUE, and FOREIGN KEY are however enforced, but not generic constraints (like a column that should have a specific value).

What's the different between RESTRICT and NO ACTION?

I'm trying to make a FK on a column, and now I'm thinking when exactly should I use ON DELETE RESTRICT? (or ON UPDATE RESTRICT). Isn't it the same as NO ACTION?
Well ON DELETE RESTRICT means you can't delete a given parent row if a child row exists that references the value for that parent row. If the parent row has no referencing child rows, then you can delete that parent row. Well its definition is the default behavior for a foreign key anyway.
Am I missing something?
They're equivalent. It even says so right there in the documentation:
NO ACTION: A keyword from standard SQL. In MySQL, equivalent to RESTRICT.
There's a difference between them in databases that have deferred checks, but MySQL doesn't.
The only difference is coming out when you define a constraint as deferrable with an initially deferred or initially immediate mode.
NO ACTION: In standard SQL, NO ACTION means no action in the sense that an attempt to delete or update a primary key value is not allowed to proceed if there is a related foreign key value in the referenced table. InnoDB rejects the delete or update operation for the parent table.
RESTRICT: Rejects the delete or update operation for the parent table. Specifying RESTRICT (or NO ACTION) is the same as omitting the ON DELETE or ON UPDATE clause. (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.)
See:
SQL SET CONTRAINS

Difference between MySQL's on update / delete "NO ACTION" vs blank

I've read this question:
What is MySQL's default ON DELETE behavior? which outlines the behaviours of different options - NO ACTION, RESTRICT, SET NULL, and CASCADE for on update / on delete actions for MySQL foreign keys.
However, there's another option - just blank. You can set it to blank - it's not a required field per se.
What does leaving it blank do? Is it the same as setting it to "NO ACTION"?
The documentation for InnoDB's foreign key handling is not clear about this. I would also speculate that the default action depends on the engine.
Most likely you are using InnoDB.
Based on my own testing, not specifying the ON action for a foreign key is the same as NO ACTION, which for InnoDB is also the same as RESTRICT. It does change output of SHOW CREATE TABLE though.

mySQL Restrict Cascade No Action settings

What is the best constraint to use on a forum table where users leave comments?
Assuming some users will be deleted at a later stage. if i delete a user who has commented, what happens to the users entry in the table?
Hope someone can explain.
There are two parts to this question:
how best to implement this? You can "soft-delete" user rows. This has the advantages of:
not losing user information
allowing users to be un-deleted
maintaining referential integrity without losing data linked to users
Soft-deleting can be implemented by adding another column to the users table, with a dateDeleted column -- if it's Null, then the user isn't deleted. I believe SO uses such a mechanism for deleting posts.
what does restrict cascade no action do? The MySQL docs say
RESTRICT: Rejects the delete or update operation for the parent table.
Specifying RESTRICT (or NO ACTION) is the same as omitting the ON
DELETE or ON UPDATE clause.
NO ACTION: A keyword from standard SQL. In MySQL, equivalent to
RESTRICT. InnoDB 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.
In other words, if you use this, you won't be able delete rows if doing so would break referential integrity.

Adding constraints in phpMyAdmin

I feel like I'm being stupid, but I can't find anywhere on the phpMyAdmin interface to add constraints to foreign keys e.g. CASCADE ON DELETE
I've looked for similar questions on here and on the phpMyAdmin wiki but I can't find anything about it.
I realise I could do this via the query interface, but I'd like to know how to do it through the graphical interface.
First, you should have your storage engine as InnoDB. Then select a table and go to 'Structure' tab.
Under the table you will see 'Relation view', click it. From there you could add constraints.
CASCADE
Whenever rows in the master (referenced) table are deleted (resp. updated), the respective rows of the child (referencing) table with a matching foreign key column will get deleted (resp. updated) as well. This is called a cascade delete (resp. update[2]).
RESTRICT
A value cannot be updated or deleted when a row exists in a foreign key table that references the value in the referenced table. Similarly, a row cannot be deleted as long as there is a reference to it from a foreign key table.
NO ACTION
NO ACTION and RESTRICT are very much alike. The main difference between NO ACTION and RESTRICT is that with NO ACTION the referential integrity check is done after trying to alter the table. RESTRICT does the check before trying to execute the UPDATE or DELETE statement. Both referential actions act the same if the referential integrity check fails: the UPDATE or DELETE statement will result in an error.
SET NULL
The foreign key values in the referencing row are set to NULL when the referenced row is updated or deleted. This is only possible if the respective columns in the referencing table are nullable. Due to the semantics of NULL, a referencing row with NULLs in the foreign key columns does not require a referenced row.
Firstly, you should choose storage engine as InnoDB.
Follow this way: click database_name -> More -> Designer