I have designed an diagram in sql server 2008.
as you can see in the photo:
Now in Value table I set the cascading delete ON for Feature and ProductDetail but I see the error below:
'Feature' table saved successfully 'ProductDetail' table saved
successfully 'Value' table
- Unable to create relationship 'ValueFeature'. Introducing FOREIGN KEY constraint 'ValueFeature' on table 'Value' may cause cycles or
multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO
ACTION, or modify other FOREIGN KEY constraints. Could not create
constraint. See previous errors.
What is it wrong with my design?
I think I have faced the same problem some years ago, in SQL server 2005. I suppose that nothing is wrong with your design. If you delete a Feature you want all the Value records to be deleted. Nothing wrong with that. If you don't have other cascades, the automatic delete will not propagate further. However, it seems that SQL Server is not clever enough to understand that, and does not allow you to have such a relationship, just because you have foreign keys that form a circle. I think that if you remove a foreign key (just for testing) and break the circle (for example delete the FK between the ProductDetail and Product) there would be no error.
Check this stackoverflow question too..
Hope I helped!
Related
I am trying to alter table product to add a constraint of type foreign key for field petCat_ID so that it references table petCategory(ID). I just created table petCat_ID and i am getting a "Cannot add or update a child row" error.
This is the commands I performed to get this error:
Alter table product
-> ADD CONSTRAINT FK_petCatID
-> FOREIGN KEY (petCat_ID)
-> REFERENCES productCategory(ID);
Any help or tips would be greatly appreciated! Note: petCat_ID is in table product and productCategory is a different table.
In my comments I've mentioned that I need a clearer idea of what kind of database structure you have, but I have a series of things that will help you work through the problem you're having.
If an ALTER statement isn't working, and you have good syntax, it is because what you are doing conflicts with an already present rule.
Sometimes, doing a DROP TABLE command, followed by creating the table again can fix problems. This can be problematic if there are dependencies that keep you from dropping the table.
When things get dire, try looking at the script you used to make the DB in the first place. Modify it and see if you can get the properties you want. Once you do, make a new database table structure and migrate your table entries over to the new database from the old one.
I made a github repository here wherein I made a third normal form version of what the customer facing Amtrack database would look like, and even wrote scripts to add data to the tables, with examples. There are images showing the ER structure. I included my creation script, broken into each table's creation in specific order. It should be a good reference for how to assign table relationships, and that will give you a good idea of what you can alter. Disclaimer I wrote it for SSMS, but I don't believe I used anything SSMS specific I THINK that code should work in MySQL.
I have just discovered my database which has been moved between a few servers in the last few months was, in one of the database dumps, converted to myisam and all the foreign key constraints nuked (not impressed). I've converted all the tables back to innodb with a php script but now I'm finding half the constraints are failing to add.
Error Code: 1452. Cannot add or update a child row: a foreign key constraint fails (`identicar2`.<result 2 when explaining filename '#sql-2a7_c0'>, CONSTRAINT `#sql-2a7_c0_ibfk_1` FOREIGN KEY (`feature_sk`) REFERENCES `tbl_feature_list` (`feature_sk`))
I'm lost now, I can't go through thousands of records manually. what is the best thing to do in order to get my database back into shape?
I can provide table structures if you want but I imagine any solution will be independant of the exact structure anyway
The simplest solution: (containing the obvious danger of losing data you may want to keep)
UPDATE table
SET fkColumn = NULL
WHERE fkColumn NOT IN (SELECT referenceColumn FROM referencedTable)
If you just want to find them:
SELECT *
FROM table
WHERE fkColumn NOT IN (SELECT referenceColumn FROM referencedTable)
I have been trying to learn from reading tutorials online and stuff but I just can't put my finger on it.
I have 2 tables at the moment (i'll have a lot more later on as I build my application) so I want to knock out this issue before expanding and coding.
I have my tables set to use InnoDB and I have each table related to each other by using user_id as foreign keys.
If i issue a DELETE query on the main users table, how can i get all records from other tables that are linked to the user_id field get deleted as well?
I know its simple, but I think I just need to ask the question myself so I can understand the answer rather than reading the answer... heh
thank a lot for any help.
Since they are InnoDB tables with proper FK relationships, you can simply use ON DELETE CASCADE in the foreign key definition. For example in one of the related tables:
FOREIGN KEY (user_id) REFERENCES users (user_id) ON DELETE CASCADE ON UPDATE CASCADE
However, this requires altering your existing schema to modify the foreign keys.
See the MySQL FOREIGN KEY docs for complete information.
You can cascade the DELETE using a DELETE trigger or using the technique Michael suggested, or you can manually write enough DELETE statements (deleting the entities from the bottom of the hierarchy upwards so you don't violate the foreign key constraints) though the latter is clearly not an ideal solution in terms of maintenance.
You may wish to use the TRIGGER approach if you want to fine tune the delete process (e.g. in case you don't want to destroy certain data related to the foreign key, or if you wanted to move it elsewhere or associate it to a different ID).
this is mysql example
ALTER TABLE table_with_foregin_key ADD FOREIGN KEY ( foreign_key_column )
REFERENCES table_name (
user_id
) ON DELETE CASCADE ON UPDATE CASCADE;
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.
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?