Cascading delete removes unintended records - mysql

I typically develop in MS Access and occasionally connect to a MySQL back end. I have a MySQL back end that isn't cascading deletes as I'd expect when I delete records. I'm wondering if it's because of how I've set up the table relationships (foreign keys). I don't know enough about MySQL to know if I've done this right. In designer view I set up the relationships using the designer view in MySQL. For a composite primary key field (InterviewID, Coder ID) in tblInterviews I created two separate relations to tblSB for each of these two primary key fields (tblSB includes a 3rd field, SBid, as its composite PK). The designer view is a little different from Access in that you can't highlight more than one field at a time to set up relationships. I did find forums that discuss the syntax for setting up the relationship with the foreign key but I don't know if it's equivalent to what I did in designer. I suspect not because currently when I try to delete a specific record (unique InterviewID, CoderID combination) ALL interview records for the CoderID in the InterviewID, CoderID combination get deleted (and this cascades through to other child tables as well). I also am wondering if I need to set up my primary key in a way that I am not currently doing (e.g., setting it up as an index, also). Any help would be appreciated. Thanks in advance.

To see what you've created, look at the DDL. (SHOW CREATE TABLE)
To enforce foreign key constraints--including cascading deletes--you probably want to use the innodb engine. The myisam engine will accept DDL that declares foreign keys, but it won't enforce them.
MySQL will let a foreign key target a non-unique column. The MySQL docs say
Deviation from SQL standards: A FOREIGN KEY constraint that references
a non-UNIQUE key is not standard SQL. It is an InnoDB extension to
standard SQL.
They call it an extension to SQL. I call it a mistake.
It means you can declare tblSB.interviewID as a foreign key referencing tblInterviews.interviewID. A standard SQL dbms wouldn't allow that.
The 5.6 docs say
However, the system does not enforce a requirement that the referenced
columns be UNIQUE or be declared NOT NULL. The handling of foreign key
references to nonunique keys or keys that contain NULL values is not
well defined for operations such as UPDATE or DELETE CASCADE. You are
advised to use foreign keys that reference only UNIQUE and NOT NULL
keys.
To my way of thinking, they're saying, "It was a bad idea, but we don't know how to fix it. So it's up to you to avoid it. We could warn you when you try it, but we're not going to do that, either."
Based on your comments, I'd say this constraint is right . . .
CONSTRAINT tblInterviewRecordtblSB
FOREIGN KEY (InterviewID, CoderID)
REFERENCES tblinterviewrecord (InterviewID, CoderID)
ON DELETE CASCADE ON UPDATE CASCADE
but these two are not, and should be deleted.
CONSTRAINT tblSB_ibfk_1
FOREIGN KEY (InterviewID)
REFERENCES tblinterviewrecord (InterviewID)
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT tblSB_ibfk_2
FOREIGN KEY (CoderID)
REFERENCES tblinterviewrecord (CoderID)
ON DELETE CASCADE ON UPDATE CASCADE

Related

PHP SQL Check Referential Integrity for whole DB

I was wondering if there was an option to check the referntial integrity of my database without checking everything manually. I must mention that I'm completely new to SQL and have the task to check the referential integrity.
With the search I found this question:
how to find records that violate referential integrity
which was already helpful, but I got quite a lot of tables and I was wondering if there was a faster way than writting hundreds of the querys in the format of the question I found.
Thanks for helping,
Yíu
EDIT:
I know that most databases check that automatically, but I'm a student and the task says
"These scripts should illustrate updating and referential integrity of your database.
! Please point explicitly where you check referential integrity (adding rows, modifying rows, deleting rows). "
So I guess I have to check it manually.
The most databases check referencing, like MySQL too. So have a look at FOREIGN KEY and REFERENCES command
http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html
Sample from MySQL page
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON DELETE CASCADE
) ENGINE=INNODB;
Child automatically check and need parent row. If you delete parents, all child rows will deleted to (ON DELETE CASCADE).

Do I have to fill foreign key values?

Do I have to fill the field of a foreign key in MySQL or any other database manager?.
I'm writing the data of a table and when I get to the field that is a FK from another table, I have to write something, is this necessary?
I understand that the value in that FK is stored inside the parent table where it comes from.
You have to provide a value unless the foreign key column is nullable.
It depends on whether the is actually a foreign key constraint in place (available in InnoDB only). In some cases frameworks, applications, or database management tools create "false" foreign keys that exist only in the application and not actually in the database. Also, the limits on how you can insert/update/delete data realted to the foreign keys can differ based on the type on constraint in place.
Here is the MYSQL documentation for definitive information:
http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
Specifically, look at the "Referential Actions" section for comments on the behavior between the tables.

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

delete 1 record from a table and automatically delete all records associated with the user_id in mysql

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;

foreign key constraint

I'm having trouble editing the data in mysql with foreigh keys. When I try to update a foreign key, it says:
Cannot add or update a child row: a foreign key constraint fails (sadsystem/products, CONSTRAINT fk_ProductRelationship11 FOREIGN KEY (size_id) REFERENCES product_sizes (size_id))
The standard way of doing this is SET CONSTRAINTS DEFERRED.
However, MySQL/InnoDB does not support this. You will have to edit your data in consistency order: that is, you'll first have to create the target row in product_sizes before you can refer to its size_id from other tables.
(If you're sure you know what you're doing (such as when importing data), you can also temporarily disable the foreign_key_checks setting, but this does not check referential integrity when you re-enable it: any constraints broken while it was disabled will stay broken.)
When you update a column which is part (or all) of a foreign key, then the new value of the complete foreign key must reference a row in the referenced table. The error message is saying you are attempting to update the foreign key to a value that does not exist in the referenced table.