If a parent table has multiple child tables, wouldn't it make more sense to declare ON DELETE CASCADE on the parent table? This way, it wouldn't be necessary to add ON DELETE CASCADE on each of the child tables.
First -- and obviously -- you might not want on delete cascade on all foreign key relationships. Each foreign key can have its own behavior, which is defined where the foreign key is defined.
Also very important. The deletion behavior is assigned on the attribute associated with the table where the deletion is going to occur. That is much more in the spirit of SQL -- and sanity -- than having a master table decide to just delete records in a bunch of other tables.
I need to delete records from relational database, where I attempt to start from the lowest children in the database.
I'm not very strong on how to approach the task. I don't want to do CASCADE delete, I actually want to do the opposite of CASCADE.
Is is correct that I have to find the entity that does not have child and start deleting the records there? and what if an entity has more that one foreign key, how do I decide on which parent table should I start to delete from?
You have to delete the child records first. If you try to delete a record that is referenced with a foreign key, you will get an error which should indicate which key has a conflict. You can then see which child table is impacted and delete the records that are referencing the foreign key, then try again.
You simply work your way up the chain. If more than one child record references a parent record, you simply delete all the child records first. If more than one parent record is referenced by a child record, it doesn't matter which parent is deleted first (or if they are deleted at all).
You don't give what database and what tools you have at hand.
You could manually diagram the database based on foreign keys or you could use a tool, such as visual studios to diagram your database.
As long as the multiple foreign relationships don't depend on one another it shouldn't matter where you start.
so i have to tables that have a relation between them - relation type: one to many.
and i thought that the following query:
DELETE Orderstbl.*, ItemsInOrdertbl.*
FROM Orderstbl INNER JOIN ItemsInOrdertbl ON Orderstbl.OrderID = ItemsInOrdertbl.OrderId
WHERE (((Orderstbl.OrderID)=26));
will delete all the rows in both tables that contain the OrderID = 26
but to my surprise it filled the following error :
could not delete from specified tables
tried to find an answer on google , didnt help much thanks in advance :D
You could also create a relationship that includes CASCADE DELETE, then when you delete from one it will delete from the other
from microsoft:
If you select the Cascade Delete Related Records check box when you
define a relationship, any time that you delete records in the primary
table, Microsoft Access automatically deletes related records in the
related table. For example, if you delete a customer record from the
Customers table, all the customer's orders are automatically deleted
from the Orders table (this includes records in the Order Details
table related to the Orders records). When you delete records from a
form or datasheet with the Cascade Delete Related Records check box
selected, Microsoft Access warns you that related records may also be
deleted. However, when you delete records using a delete query,
Microsoft Access automatically deletes the records in related tables
without displaying a warning.
Using the CASCADE DELETE is a simple and clean way to make sure the correct records are removed from both tables.
Here is another article discussing CASCADE DELETE with MS-Access.
Delete one or more records from an Access database
If you have a foreign key set between columns in two tables, you have to be sure to delete the child column first, and then the master. The proper way to do this is to set a constraint upon deletion of the master, such as UPDATE or DELETE. The constraint takes care of the foreign key relations, so you never wind up with orphan rows all over the place.
To create the constraints in MySQL (for example)...
[CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name, ...)
REFERENCES tbl_name (index_col_name,...)
[ON DELETE reference_option]
[ON UPDATE reference_option]
The other option is to do it programmatically, deleting the row in child tables first, and then the master.
How do primary key , foreign key and unique constraints work? i mean in what sequence?
Like, when a child table has a FK, and a record is inserted into it , which doesn't exists in the parent table, then is this record first inserted into the child table & then the constraint checks in the Parent table if this record exists or not, and if it doesn't finds it then it rollbacks and removes the record from the Child table. is this the order of working?
or, does first SQL gets the record(on which the FK is made) from the insert query, & matches it with the parent table records, and ceases the insert when matching record is not found, while insertion itself and doesn't inserts the row in the child table?
Similarly, for the primary key, if a duplicate record is inserted in a table, then is it first inserted then checked or before insertion first it is matched with existing records, and if it is a duplicate one, then the query is ceased.
Logically speaking, all constraints are supposed to be checked simultaneously against the entire result of an UPDATE, INSERT or DELETE statement. The constraints are evaluated as if the modification to all rows had already happened and if any constraint would be violated then the modification is not permitted.
You need the basic of rdbms reference. Here is the free resource: http://msdn.microsoft.com/en-us/library/aa933098%28v=SQL.80%29.aspx
Consider the logical (conceptual) tables deleted and inserted that are accessible to a TRIGGER. Even these are only concepts. Who knows what's going on under the covers? ...well, someone is bound to know... but do you care what's going on under the covers? At the conceptual level, it either succeeds or fails or you can manipulate the outcome in a trigger. What more do you need to know? ;)
I use ON DELETE CASCADE regularly but I never use ON UPDATE CASCADE as I am not so sure in what situation it will be useful.
For the sake of discussion let see some code.
CREATE TABLE parent (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id)
);
CREATE TABLE child (
id INT NOT NULL AUTO_INCREMENT, parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON DELETE CASCADE
);
For ON DELETE CASCADE, if a parent with an id is deleted, a record in child with parent_id = parent.id will be automatically deleted. This should be no problem.
This means that ON UPDATE CASCADE will do the same thing when id of the parent is updated?
If (1) is true, it means that there is no need to use ON UPDATE CASCADE if parent.id is not updatable (or will never be updated) like when it is AUTO_INCREMENT or always set to be TIMESTAMP. Is that right?
If (2) is not true, in what other kind of situation should we use ON UPDATE CASCADE?
What if I (for some reason) update the child.parent_id to be something not existing, will it then be automatically deleted?
Well, I know, some of the question above can be test programmatically to understand but I want also know if any of this is database vendor dependent or not.
Please shed some light.
It's true that if your primary key is just an identity value auto incremented, you would have no real use for ON UPDATE CASCADE.
However, let's say that your primary key is a 10 digit UPC bar code and because of expansion, you need to change it to a 13-digit UPC bar code. In that case, ON UPDATE CASCADE would allow you to change the primary key value and any tables that have foreign key references to the value will be changed accordingly.
In reference to #4, if you change the child ID to something that doesn't exist in the parent table (and you have referential integrity), you should get a foreign key error.
Yes, it means that for example if you do UPDATE parent SET id = 20 WHERE id = 10 all children parent_id's of 10 will also be updated to 20
If you don't update the field the foreign key refers to, this setting is not needed
Can't think of any other use.
You can't do that as the foreign key constraint would fail.
I think you've pretty much nailed the points!
If you follow database design best practices and your primary key is never updatable (which I think should always be the case anyway), then you never really need the ON UPDATE CASCADE clause.
Zed made a good point, that if you use a natural key (e.g. a regular field from your database table) as your primary key, then there might be certain situations where you need to update your primary keys. Another recent example would be the ISBN (International Standard Book Numbers) which changed from 10 to 13 digits+characters not too long ago.
This is not the case if you choose to use surrogate (e.g. artifically system-generated) keys as your primary key (which would be my preferred choice in all but the most rare occasions).
So in the end: if your primary key never changes, then you never need the ON UPDATE CASCADE clause.
Marc
A few days ago I've had an issue with triggers, and I've figured out that ON UPDATE CASCADE can be useful. Take a look at this example (PostgreSQL):
CREATE TABLE club
(
key SERIAL PRIMARY KEY,
name TEXT UNIQUE
);
CREATE TABLE band
(
key SERIAL PRIMARY KEY,
name TEXT UNIQUE
);
CREATE TABLE concert
(
key SERIAL PRIMARY KEY,
club_name TEXT REFERENCES club(name) ON UPDATE CASCADE,
band_name TEXT REFERENCES band(name) ON UPDATE CASCADE,
concert_date DATE
);
In my issue, I had to define some additional operations (trigger) for updating the concert's table. Those operations had to modify club_name and band_name. I was unable to do it, because of reference. I couldn't modify concert and then deal with club and band tables. I couldn't also do it the other way. ON UPDATE CASCADE was the key to solve the problem.
The ON UPDATE and ON DELETE specify which action will execute when a row in the parent table is updated and deleted. The following are permitted actions : NO ACTION, CASCADE, SET NULL, and SET DEFAULT.
Delete actions of rows in the parent table
If you delete one or more rows in the parent table, you can set one of the following actions:
ON DELETE NO ACTION: SQL Server raises an error and rolls back the delete action on the row in the parent table.
ON DELETE CASCADE: SQL Server deletes the rows in the child table that is corresponding to the row deleted from the parent table.
ON DELETE SET NULL: SQL Server sets the rows in the child table to NULL if the corresponding rows in the parent table are deleted. To execute this action, the foreign key columns must be nullable.
ON DELETE SET DEFAULT: SQL Server sets the rows in the child table to their default values if the corresponding rows in the parent table are deleted. To execute this action, the foreign key columns must have default definitions. Note that a nullable column has a default value of NULL if no default value specified.
By default, SQL Server appliesON DELETE NO ACTION if you don’t explicitly specify any action.
Update action of rows in the parent table
If you update one or more rows in the parent table, you can set one of the following actions:
ON UPDATE NO ACTION: SQL Server raises an error and rolls back the update action on the row in the parent table.
ON UPDATE CASCADE: SQL Server updates the corresponding rows in the child table when the rows in the parent table are updated.
ON UPDATE SET NULL: SQL Server sets the rows in the child table to NULL when the corresponding row in the parent table is updated. Note that the foreign key columns must be nullable for this action to execute.
ON UPDATE SET DEFAULT: SQL Server sets the default values for the rows in the child table that have the corresponding rows in the parent table updated.
FOREIGN KEY (foreign_key_columns)
REFERENCES parent_table(parent_key_columns)
ON UPDATE <action>
ON DELETE <action>;
See the reference tutorial.
It's an excellent question, I had the same question yesterday. I thought about this problem, specifically SEARCHED if existed something like "ON UPDATE CASCADE" and fortunately the designers of SQL had also thought about that. I agree with Ted.strauss, and I also commented Noran's case.
When did I use it? Like Ted pointed out, when you are treating several databases at one time, and the modification in one of them, in one table, has any kind of reproduction in what Ted calls "satellite database", can't be kept with the very original ID, and for any reason you have to create a new one, in case you can't update the data on the old one (for example due to permissions, or in case you are searching for fastness in a case that is so ephemeral that doesn't deserve the absolute and utter respect for the total rules of normalization, simply because will be a very short-lived utility)
So, I agree in two points:
(A.) Yes, in many times a better design can avoid it; BUT
(B.) In cases of migrations, replicating databases, or solving emergencies, it's a GREAT TOOL that fortunately was there when I went to search if it existed.
My comment is mainly in reference to point #3: under what circumstances is ON UPDATE CASCADE applicable if we're assuming that the parent key is not updateable? Here is one case.
I am dealing with a replication scenario in which multiple satellite databases need to be merged with a master. Each satellite is generating data on the same tables, so merging of the tables to the master leads to violations of the uniqueness constraint. I'm trying to use ON UPDATE CASCADE as part of a solution in which I re-increment the keys during each merge. ON UPDATE CASCADE should simplify this process by automating part of the process.
To add to other great answers here it is important to use ON UPDATE CASCADE (or on DELETE CASCADE...) cautiously. Operations on tables with this specification require exclusive lock on underlaying relations.
If you have multiple CASCADE definitions in one table (as in other answer), and especially multiple tables using same definitions, and multiple users updating, this can create a deadlock when one process acquires exclusive lock on first underlaying table, other exclusive lock on second, and they block out each other by none of them being able to get both (all) exclusive locks to perform operation.