mySQL Restrict Cascade No Action settings - mysql

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.

Related

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

Can I not enforce referential integrity in MySQL

I have a SQL table called "user" and a table "login" that has a foreign key constraint to a user. I want to be able to delete a row in the user table, even if there are login rows that reference it. Right now the database stops me from doing this.
Does anyone know how I can alter the table (through SQL or preferably through PHPmyAdmin to allow me to do this?
The tables were created automatically through Django.
Edit: To clarify: I don't want to cascade the delete. That is, I want the rows in the Login table to remain even though the user they reference is gone.
If you want this kind of behavior you have to create the foreign key with an ON DELETE CASCADE clause. With an ON DELETE CASCADE foreign key all rows referencing the user will be deleted with the user.
See: http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html
Edit: If you want to keep the user_id in your login tables you just have to drop the foreign key. Anyway, If you are asking this is because you should probably do a logical delete instead of a physical delete: Physical vs. logical / soft delete of database record?
Proper way to do this is to mark offending users as "inactive" so they can't login and you still maintain referential integrity of your database.
Deleting data from master table that has referential integrity links to some data in slave table is bad praxis.

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

Foreign key constraints: When to use ON UPDATE and ON DELETE

I'm designing my database schema using MySQL Workbench, which is pretty cool because you can do diagrams and it converts them :P
Anyways, I've decided to use InnoDB because of it's Foreign Key support. One thing I noticed though is that it allows you to set On Update and on Delete options for foreign keys. Can someone explain where "Restrict", "Cascade" and set null could be used in a simple example?
For example, say I have a user table which includes a userID. And say I have a message table message which is a many-to-many which has 2 foreign keys (which reference the same primary key, userID in the user table). Is setting the On Update and On Delete options any useful in this case? If so, which one do I choose? If this isn't a good example, could you please come up with a good example to illustrate how these could be useful?
Thanks
Do not hesitate to put constraints on the database. You'll be sure to have a consistent database, and that's one of the good reasons to use a database. Especially if you have several applications requesting it (or just one application but with a direct mode and a batch mode using different sources).
With MySQL you do not have advanced constraints like you would have in postgreSQL but at least the foreign key constraints are quite advanced.
We'll take an example, a company table with a user table containing people from theses company
CREATE TABLE COMPANY (
company_id INT NOT NULL,
company_name VARCHAR(50),
PRIMARY KEY (company_id)
) ENGINE=INNODB;
CREATE TABLE USER (
user_id INT,
user_name VARCHAR(50),
company_id INT,
INDEX company_id_idx (company_id),
FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;
Let's look at the ON UPDATE clause:
ON UPDATE RESTRICT : the default : if you try to update a company_id in table COMPANY the engine will reject the operation if one USER at least links on this company.
ON UPDATE NO ACTION : same as RESTRICT.
ON UPDATE CASCADE : the best one usually : if you update a company_id in a row of table COMPANY the engine will update it accordingly on all USER rows referencing this COMPANY (but no triggers activated on USER table, warning). The engine will track the changes for you, it's good.
ON UPDATE SET NULL : if you update a company_id in a row of table COMPANY the engine will set related USERs company_id to NULL (should be available in USER company_id field). I cannot see any interesting thing to do with that on an update, but I may be wrong.
And now on the ON DELETE side:
ON DELETE RESTRICT : the default : if you try to delete a company_id Id in table COMPANY the engine will reject the operation if one USER at least links on this company, can save your life.
ON DELETE NO ACTION : same as RESTRICT
ON DELETE CASCADE : dangerous : if you delete a company row in table COMPANY the engine will delete as well the related USERs. This is dangerous but can be used to make automatic cleanups on secondary tables (so it can be something you want, but quite certainly not for a COMPANY<->USER example)
ON DELETE SET NULL : handful : if you delete a COMPANY row the related USERs will automatically have the relationship to NULL. If Null is your value for users with no company this can be a good behavior, for example maybe you need to keep the users in your application, as authors of some content, but removing the company is not a problem for you.
usually my default is: ON DELETE RESTRICT ON UPDATE CASCADE. with some ON DELETE CASCADE for track tables (logs--not all logs--, things like that) and ON DELETE SET NULL when the master table is a 'simple attribute' for the table containing the foreign key, like a JOB table for the USER table.
Edit
It's been a long time since I wrote that. Now I think I should add one important warning. MySQL has one big documented limitation with cascades. Cascades are not firing triggers. So if you were over confident enough in that engine to use triggers you should avoid cascades constraints.
http://dev.mysql.com/doc/refman/5.6/en/triggers.html
MySQL triggers activate only for changes made to tables by SQL statements. They do not activate for changes in views, nor by changes to tables made by APIs that do not transmit SQL statements to the MySQL Server
http://dev.mysql.com/doc/refman/5.6/en/stored-program-restrictions.html#stored-routines-trigger-restrictions
==> See below the last edit, things are moving on this domain
Triggers are not activated by foreign key actions.
And I do not think this will get fixed one day. Foreign key constraints are managed by the InnoDb storage and Triggers are managed by the MySQL SQL engine. Both are separated. Innodb is the only storage with constraint management, maybe they'll add triggers directly in the storage engine one day, maybe not.
But I have my own opinion on which element you should choose between the poor trigger implementation and the very useful foreign keys constraints support. And once you'll get used to database consistency you'll love PostgreSQL.
12/2017-Updating this Edit about MySQL:
as stated by #IstiaqueAhmed in the comments, the situation has changed on this subject. So follow the link and check the real up-to-date situation (which may change again in the future).
You'll need to consider this in context of the application. In general, you should design an application, not a database (the database simply being part of the application).
Consider how your application should respond to various cases.
The default action is to restrict (i.e. not permit) the operation, which is normally what you want as it prevents stupid programming errors. However, on DELETE CASCADE can also be useful. It really depends on your application and how you intend to delete particular objects.
Personally, I'd use InnoDB because it doesn't trash your data (c.f. MyISAM, which does), rather than because it has FK constraints.
Addition to #MarkR answer - one thing to note would be that many PHP frameworks with ORMs would not recognize or use advanced DB setup (foreign keys, cascading delete, unique constraints), and this may result in unexpected behaviour.
For example if you delete a record using ORM, and your DELETE CASCADE will delete records in related tables, ORM's attempt to delete these related records (often automatic) will result in error.

Linq to sql - delete some related records

I´m using linq to sql and I have a lot of tables with foreign keys leading to the UserId.
Is it possible to have some of these foreign tables cleaned upon deletion.
For example I want the users profile (other table) to be deleted automatically with the user but not the users forum posts.
Is this possible or do I have to handle this with code?
I think this link is very usefull.
LINQ to SQL does not support or
recognize cascade-delete operations.
If you want to delete a row in a table
that has constraints against it, you
must complete either of the following
tasks:
Set the ON DELETE CASCADE rule in the foreign-key constraint in the
database.
Use your own code to first delete the child objects that prevent the
parent object from being deleted.
I am not sure with code, but couldn't you set the Cascade on Delete option in SQL?