Delete record with foreign key to itself [duplicate] - mysql

I have a MySQL table whose definition is as follows:
CREATE TABLE `guestbook` (
`Id` int(10) unsigned NOT NULL,
`ThreadId` int(10) unsigned NOT NULL,
PRIMARY KEY (`Id`),
KEY `ThreadId` (`ThreadId`),
CONSTRAINT `guestbook_ibfk_1` FOREIGN KEY (`ThreadId`) REFERENCES `guestbook` (`Id`)
) ENGINE=InnoDB;
and currently there's only 1 row in the table:
mysql> select * from guestbook;
+-----+----------+
| Id | ThreadId |
+-----+----------+
| 211 | 211 |
+-----+----------+
The problem is that there's no way to delete this row without breaking the constraint.
mysql> delete from guestBook;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`polaris`.`guestbook`, CONSTRAINT `guestbook_ibfk_1` FOREIGN KEY (`ThreadId`) REFERENCES `guestbook` (`Id`))
As the ThreadId column was defined not null, it is also impossible to set the ThreadId to a different value temporarily to delete the row. Is there a way to delete the row without changing the definition of the table or dropping the entire table?

You can temporarily disable foreign key constraints with this query:
SET foreign_key_checks = 0;

If you put an ON DELETE CASCADE action on your foreign key, you should be able to delete rows that are self-referencing.
CONSTRAINT `guestbook_ibfk_1` FOREIGN KEY (`ThreadId`) REFERENCES `guestbook` (`Id`) ON DELETE CASCADE
The benefit this has over using ON DELETE SET NULL is that you don't have to alter your schema to make the "ThreadId" column nullable.

There are several workarounds. The approach suggested by others ...
SET foreign_key_checks = 0;
... will disable the foreign keys of every table. This is not suitable for use in a shared environment.
Another approach is to drop the foreign key using
ALTER TABLE `guestbook`
DROP FOREIGN KEY `guestbook_ibfk_1`
/
We can sort out the data using DML, and then reinstate the foreign key using:
ALTER TABLE `guestbook`
ADD CONSTRAINT `guestbook_ibfk_1` FOREIGN KEY (`ThreadId`)
REFERENCES `guestbook` (`Id`)
/
But is there a way to change the data without executing any DDL? Well, we can insert a new record and change the current record to reference it:
INSERT INTO `guestbook` VALUES (212, 211)
/
UPDATE `guestbook`
SET `ThreadId` = 212
WHERE `Id` = 211
/
Astute observers will have noticed that we have still ended up with a co-dependency, only between records. So we haven't really advanced; we now have two records we cannot delete, instead of one. (Incidentally this applies to whatever DML we might execute while the foreign key is dropped or disabled). So, perhaps we need to reconsider of the data model. Are we modelling a graph with circular dependencies or a hierarchy?
A hierarchical data structure needs at least one root node, a record on which other records can depend but which itself depends on no record. The usual way of implementing this is to make the foreign key column optional. At the toppermost level of the hierarchy the record must have a NULL in that column. Whether there should be only one such root node or whether several would be allowed is a matter for your business rules.
ALTER TABLE `guestbook` MODIFY `ThreadId` int(10) unsigned
/
In modelling terms this is not different from a record which is its own master, but it is a more intuitive solution.

The inability to delete a self-referencing row is a longstanding known bug/outstanding feature request in MySQL.
In many situations where you rub up against this problem you can NULL the foreign key before executing the delete, so your workaround affects only the rows you intend (uses the same WHERE clause).

Ya temporarily disable the foreign key
set foreign_key_checks=0;

If you set an ON DELETE SET NULL on my Foreign Key, it let's me delete a self-referencing. If I don't specify an ON DELETE, MySQL defaults to RESTRICT.
Of course, make sure the column is NULLABLE. You may also try SET DEFAULT depending on what the default is. But remember NO ACTION is just an alias to RESTRICT in MySQL!
Only tested on MySQL 5.6 (which was not released when this question was originally posted).

Related

InnoDB - bidirectional many-to-many foreign key check

I'm trying to establish a many-to-many relationship within a table: a keyword can related to another keyword, and when that relation is added, the other direction must also be established.
Running on 10.5.9-MariaDB.
CREATE TABLE `related_keywords` (
`relation_id` int(12) NOT NULL AUTO_INCREMENT COMMENT 'Laravel/Eloquent pk crutch',
`keyword_1` bigint(20) unsigned NOT NULL,
`keyword_2` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`relation_id`),
UNIQUE KEY `rel_kw_left_to_right` (`keyword_1`,`keyword_2`),
UNIQUE KEY `rel_kw_right_to_left` (`keyword_2`,`keyword_1`),
CONSTRAINT `fk_rel_kw_1_exists` FOREIGN KEY (`keyword_1`) REFERENCES `keywords` (`keyword_id`) ON DELETE CASCADE,
CONSTRAINT `fk_rel_kw_2_exists` FOREIGN KEY (`keyword_2`) REFERENCES `keywords` (`keyword_id`) ON DELETE CASCADE,
CONSTRAINT `fk_related_kw_lr` FOREIGN KEY (`keyword_1`, `keyword_2`) REFERENCES `related_keywords` (`keyword_2`, `keyword_1`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `ck_rel_kw_differ` CHECK (`keyword_1` <> `keyword_2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
In order to add one, the other must also be added. Likewise, removing one row must remove the other. However, I can't add the first one without adding the second one due to the foreign key check enforcing this:
INSERT INTO related_keywords (keyword_1, keyword_2) VALUES
(119250770368532480, 119251038153871360),
(119251038153871360, 119250770368532480);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`keyword_db`.`related_keywords`, CONSTRAINT `fk_related_keyword_lr` FOREIGN KEY (`keyword_1`, `keyword_2`) REFERENCES `related_keywords` (`keyword_2`, `keyword_1`) ON DELETE CASCADE ON UPDATE )
Now, I tried running it in a transaction, but it still seems to check the foreign keys (which I found odd). The only way that I can actually get it to add is to disable foreign key checks during the INSERT, which I really don't like.
The ideal solution here would be to make it so that, on the application level, all I had to do was:
INSERT INTO related_keywords (keyword_1, keyword_2) VALUES (119250770368532480, 119251038153871360);
and the matching row would be automatically added as well, with no problem from the fk_related_kw_lr foreign key check.
I've searched through docs for MariaDB and InnoDB in general and even with MariaDB 10.x's newer features I can't seem to work out a way to
Temporarily disable a single (out of several) constraint
Defer constraint checks until the end of the transaction
...and also insert the matching opposite-direction row when the first one is inserted
Any ideas?
The PK is useless
Only one UNIQUE is needed
3 uniques slows down inserts.
Optimal many-to-many: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table
I doubt if you need "cascade".
Drop the FKs, they can be more trouble than they are worth.
Instead of adding 2 rows, consider adding one row with the following. (This may help or may complicate things, depending of what uses you have for this table.)
LEAST(1234, 2345),
GREATEST(1234, 2345)

#1452 - Cannot add or update a child row: a foreign key constraint fails the query is failing [duplicate]

I'm having a bit of a strange problem. I'm trying to add a foreign key to one table that references another, but it is failing for some reason. With my limited knowledge of MySQL, the only thing that could possibly be suspect is that there is a foreign key on a different table referencing the one I am trying to reference.
I've done a SHOW CREATE TABLE query on both tables, sourcecodes_tags is the table with the foreign key, sourcecodes is the referenced table.
CREATE TABLE `sourcecodes` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) unsigned NOT NULL,
`language_id` int(11) unsigned NOT NULL,
`category_id` int(11) unsigned NOT NULL,
`title` varchar(40) CHARACTER SET utf8 NOT NULL,
`description` text CHARACTER SET utf8 NOT NULL,
`views` int(11) unsigned NOT NULL,
`downloads` int(11) unsigned NOT NULL,
`time_posted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `language_id` (`language_id`),
KEY `category_id` (`category_id`),
CONSTRAINT `sourcecodes_ibfk_3` FOREIGN KEY (`language_id`) REFERENCES `languages` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `sourcecodes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `sourcecodes_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
CREATE TABLE `sourcecodes_tags` (
`sourcecode_id` int(11) unsigned NOT NULL,
`tag_id` int(11) unsigned NOT NULL,
KEY `sourcecode_id` (`sourcecode_id`),
KEY `tag_id` (`tag_id`),
CONSTRAINT `sourcecodes_tags_ibfk_1` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
This is the code that generates the error:
ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE
Quite likely your sourcecodes_tags table contains sourcecode_id values that no longer exists in your sourcecodes table. You have to get rid of those first.
Here's a query that can find those IDs:
SELECT DISTINCT sourcecode_id FROM
sourcecodes_tags tags LEFT JOIN sourcecodes sc ON tags.sourcecode_id=sc.id
WHERE sc.id IS NULL;
I had the same issue with my MySQL database but finally, I got a solution which worked for me.
Since in my table everything was fine from the mysql point of view(both tables should use InnoDB engine and the datatype of each column should be of the same type which takes part in foreign key constraint).
The only thing that I did was to disable the foreign key check and later on enabled it after performing the foreign key operation.
Steps that I took:
SET foreign_key_checks = 0;
alter table tblUsedDestination add constraint f_operatorId foreign key(iOperatorId) references tblOperators (iOperatorId); Query
OK, 8 rows affected (0.23 sec) Records: 8 Duplicates: 0 Warnings: 0
SET foreign_key_checks = 1;
Use NOT IN to find where constraints are constraining:
SELECT column FROM table WHERE column NOT IN
(SELECT intended_foreign_key FROM another_table)
so, more specifically:
SELECT sourcecode_id FROM sourcecodes_tags WHERE sourcecode_id NOT IN
(SELECT id FROM sourcecodes)
EDIT: IN and NOT IN operators are known to be much faster than the JOIN operators, as well as much easier to construct, and repeat.
Truncate the tables and then try adding the FK Constraint.
I know this solution is a bit awkward but it does work 100%. But I agree that this is not an ideal solution to deal with problem, but I hope it helps.
For me, this problem was a little different and super easy to check and solve.
You must ensure BOTH of your tables are InnoDB. If one of the tables, namely the reference table is a MyISAM, the constraint will fail.
SHOW TABLE STATUS WHERE Name = 't1';
ALTER TABLE t1 ENGINE=InnoDB;
This also happens when setting a foreign key to parent.id to child.column if the child.column has a value of 0 already and no parent.id value is 0
You would need to ensure that each child.column is NULL or has value that exists in parent.id
And now that I read the statement nos wrote, that's what he is validating.
I had the same problem today. I tested for four things, some of them already mentioned here:
Are there any values in your child column that don't exist in the parent column (besides NULL, if the child column is nullable)
Do child and parent columns have the same datatype?
Is there an index on the parent column you are referencing? MySQL seems to require this for performance reasons (http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html)
And this one solved it for me: Do both tables have identical collation?
I had one table in UTF-8 and the other in iso-something. That didn't work. After changing the iso-table to UTF-8 collation the constraints could be added without problems. In my case, phpMyAdmin didn't even show the child table in iso-encoding in the dropdown for creating the foreign key constraint.
It seems there is some invalid value for the column line 0 that is not a valid foreign key so MySQL cannot set a foreign key constraint for it.
You can follow these steps:
Drop the column which you have tried to set FK constraint for.
Add it again and set its default value as NULL.
Try to set a foreign key constraint for it again.
I'd the same problem, I checked rows of my tables and found there was some incompatibility with the value of fields that I wanted to define a foreign key. I corrected those value, tried again and the problem was solved.
I end up delete all the data in my table, and run alter again. It works. Not the brilliant one, but it save a lot time, especially your application is still in development stage without any customer data.
try this
SET foreign_key_checks = 0;
ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE
SET foreign_key_checks = 1;
I had this exact same problem about three different times. In each instance it was because one (or more) of my records did not conform to the new foreign key. You may want to update your existing records to follow the syntax constraints of the foreign key before trying to add the key itself. The following example should generally isolate the problem records:
SELECT * FROM (tablename)
WHERE (candidate key) <> (proposed foreign key value)
AND (candidate key) <> (next proposed foreign key value)
repeat AND (candidate key) <> (next proposed foreign key value) within your query for each value in the foreign key.
If you have a ton of records this can be difficult, but if your table is reasonably small it shouldn't take too long. I'm not super amazing in SQL syntax, but this has always isolated the issue for me.
Empty both your tables' data and run the command. It will work.
I was getting this error when using Laravel and eloquent, trying to make a foreign key link would cause a 1452. The problem was lack of data in the linked table.
Please see here for an example: http://mstd.eu/index.php/2016/12/02/laravel-eloquent-integrity-constraint-violation-1452-foreign-key-constraint/
You just need to answer one question:
Is your table already storing data? (Especially the table included foreign key.)
If the answer is yes, then the only thing you need to do is to delete all the records, then you are free to add any foreign key to your table.
Delete instruction: From child(which include foreign key table) to parent table.
The reason you cannot add in foreign key after data entries is due to the table inconsistency, how are you going to deal with a new foreign key on the former data-filled the table?
If the answer is no, then follow other instructions.
I was readying this solutions and this example may help.
My database have two tables (email and credit_card) with primary keys for their IDs. Another table (client) refers to this tables IDs as foreign keys. I have a reason to have the email apart from the client data.
First I insert the row data for the referenced tables (email, credit_card) then you get the ID for each, those IDs are needed in the third table (client).
If you don't insert first the rows in the referenced tables, MySQL wont be able to make the correspondences when you insert a new row in the third table that reference the foreign keys.
If you first insert the referenced rows for the referenced tables, then the row that refers to foreign keys, no error occurs.
Hope this helps.
Make sure the value is in the other table otherwise you will get this error, in the assigned corresponding column.
So if it is assigned column is assigned to a row id of another table , make sure there is a row that is in the table otherwise this error will appear.
you can try this exapmple
START TRANSACTION;
SET foreign_key_checks = 0;
ALTER TABLE `job_definers` ADD CONSTRAINT `job_cities_foreign` FOREIGN KEY
(`job_cities`) REFERENCES `drop_down_lists`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
SET foreign_key_checks = 1;
COMMIT;
Note : if you are using phpmyadmin just uncheck Enable foreign key checks
as example
hope this soloution fix your problem :)
UPDATE sourcecodes_tags
SET sourcecode_id = NULL
WHERE sourcecode_id NOT IN (
SELECT id FROM sourcecodes);
should help to get rid of those IDs. Or if null is not allowed in sourcecode_id, then remove those rows or add those missing values to the sourcecodes table.
I had the same problem and found solution, placing NULL instead of NOT NULL on foreign key column. Here is a query:
ALTER TABLE `db`.`table1`
ADD COLUMN `col_table2_fk` INT UNSIGNED NULL,
ADD INDEX `col_table2_fk_idx` (`col_table2_fk` ASC),
ADD CONSTRAINT `col_table2_fk1`
FOREIGN KEY (`col_table2_fk`)
REFERENCES `db`.`table2` (`table2_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
MySQL has executed this query!
In my case, I created a new table with the same structure, created the relationships with the other tables, then extracted the data in CSV from the old table that has the problem, then imported the CSV to the new table and disabled foreign key checking and disabled import interruption, all my data are inserted to the new table that has no problem successfully, then deleted the old table.
It worked for me.

Error altering primary key column in mysql table

I am very new to SQL and MySQL. I am trying to modify a primary key column in a table so that it auto-increments. This primary key is also a foreign key in another table. I am not able to modify this column due to an error related to the foreign key in the other table. Here is the error:
mysql> desc favourite_food;
+-----------+----------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+----------------------+------+-----+---------+-------+
| person_id | smallint(5) unsigned | NO | PRI | 0 | |
| food | varchar(20) | NO | PRI | | |
+-----------+----------------------+------+-----+---------+-------+
2 rows in set (0.09 sec)
mysql> alter table person modify person_id smallint unsigned auto_increment;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 22
Current database: bank
ERROR 1833 (HY000): Cannot change column 'person_id': used in a foreign key cons
traint 'fk_fav_food_person_id' of table 'bank.favourite_food'
mysql>
I'm sure it is something simple, but I can't figure out why and teh book I am following does not indicate why. Thanks.
Do it something like this
--Drop fk
ALTER TABLE favourite_food DROP FOREIGN KEY fk_fav_food_person_id;
--Alter your pk
ALTER TABLE person modify person_id smallint unsigned auto_increment;
--Recreate fk
ALTER TABLE favourite_food ADD CONSTRAINT fk_fav_food_person_id FOREIGN KEY (person_id) REFERENCES person (person_id) ON DELETE CASCADE;
Haven't checked syntax exactly, but should be close
Execute your SQL again and then run
show engine innodb status
Type the above command onto your MySQL command prompt. It should help you with more info on why the SQL failed to execute.
Try this otherwise:
show innodb status
Take a look here:
Error code 1005, SQL state HY000: Can't create table errno: 150
You cannot alter a primary key as it is referenced as a foreign key in other table. This is because of the referential integrity constraint.
Referential Integrity Although the main purpose of a foreign key constraint is to control the data that can be stored in the foreign
key table, it also controls changes to data in the primary key table.The constraint enforces referential integrity by guaranteeing that changes cannot be made to data in the primary key table if those changes invalidate the link to data in the foreign key table. If an attempt is made to delete the row in a primary key table or to change a primary key value, the action will fail when the deleted or changed primary key value corresponds to a value in the foreign key constraint of another table. To successfully change or delete a row in a foreign key constraint, you must first either delete the foreign key data in the foreign key table or change the foreign key data in the foreign key table, which links the foreign key to different primary key data.
Cascading Referential Integrity
By using cascading referential integrity constraints, you can define
the actions that the Database Engine takes when a user tries to delete
or update a key to which existing foreign keys point. The following
cascading actions can be defined.
NO ACTION
The Database Engine raises an error and the delete or update action on
the row in the parent table is rolled back.
CASCADE
Corresponding rows are updated or deleted in the referencing table
when that row is updated or deleted in the parent table. CASCADE
cannot be specified if a timestamp column is part of either the
foreign key or the referenced key. ON DELETE CASCADE cannot be
specified for a table that has an INSTEAD OF DELETE trigger. ON UPDATE
CASCADE cannot be specified for tables that have INSTEAD OF UPDATE
triggers.
SET NULL
All the values that make up the foreign key are set to NULL when the
corresponding row in the parent table is updated or deleted. For this
constraint to execute, the foreign key columns must be nullable.
Cannot be specified for tables that have INSTEAD OF UPDATE triggers.
SET DEFAULT
All the values that make up the foreign key are set to their default
values if the corresponding row in the parent table is updated or
deleted. For this constraint to execute, all foreign key columns must
have default definitions. If a column is nullable, and there is no
explicit default value set, NULL becomes the implicit default value of
the column. Cannot be specified for tables that have INSTEAD OF UPDATE
triggers.
CASCADE, SET NULL, SET DEFAULT and NO ACTION can be combined on tables
that have referential relationships with each other. If the Database
Engine encounters NO ACTION, it stops and rolls back related CASCADE,
SET NULL and SET DEFAULT actions. When a DELETE statement causes a
combination of CASCADE, SET NULL, SET DEFAULT and NO ACTION actions,
all the CASCADE, SET NULL and SET DEFAULT actions are applied before
the Database Engine checks for any NO ACTION.

MySQL: delete a row ignoring foreign key constraint

so I am working on a few tables and there are some data inconsistency between them... One or two tables have a foreign key constraint on a particular table (call it table X), but that table has multiple rows with the foreign key column.
What I want to do is to remove the duplicated rows in table X, but the foreign key constraint is preventing me from doing this. Is there a way to force delete the rows while ignoring the foreign key constraint since I know what I'm doing?
SET foreign_key_checks = 0;
That will prevent MySQL from checking foreign keys. Make sure to set it back to 1 when you are done though.
Also, you could always drop the foreign key and then add it later if you wanted to only affect a singular key
ALTER TABLE tableName DROP FOREIGN KEY fk;
Simply execute as follows:
Disable foreign key check
SET foreign_key_checks = 0;
Delete your records
DELETE FROM table_name WHERE {conditions};
Enable foreign key check
SET foreign_key_checks = 1;
Credit: https://www.knowledgewalls.com/johnpeter/books/mysql/how-to-ignore-constraints-while-insertupdate-or-delete-records-in-mysql
As some people already pointed out, ignoring a restricting foreign key leaves you with database inconsistencies. Preventing DELETEs is something you want in such cases.
You should better delete depending rows prior to the main query:
DELETE FROM cities WHERE country_id=3;
-- Afterwards you delete rows from the parent table without error:
DELETE FROM countries WHERE country_id=3;
Or, even better, change the foreign key once, so it does the deletion automatically (cascading):
ALTER TABLE cities DROP FOREIGN KEY `fk.cities.country_id`;
ALTER TABLE cities ADD CONSTRAINT `fk.cities.country_id` FOREIGN KEY (country_id)
REFERENCES countries (id) ON UPDATE CASCADE ON DELETE CASCADE;
-- From now on, just delete from the parent table:
DELETE FROM countries WHERE country_id=3;
To expand on the accepted answer, you have to specify the constraint name after DROP FOREIGN KEY
You can check the constraint name by issuing SHOW CREATE TABLE.
> SHOW CREATE TABLE tbl_name
Create Table: CREATE TABLE `tbl_name` (
`id` int(11) DEFAULT NULL,
`foo_id` int(11) DEFAULT NULL,
CONSTRAINT `foo_ibfk_1` FOREIGN KEY (`foo_id`)
)
In this case, "foo_ibfk_1" is the constraint name. So you can write:
ALTER TABLE tableName DROP FOREIGN KEY foo_ibfk_1;

MySQL Foreign Key On Delete

I am trying to figure out relationships and deletion options.
I have two tables, User and UserStaff, with a 1:n relationship from User to UserStaff (a user can have multiple staff members).
When my User is deleted, I want to delete all of the UserStaff tables associated with that User. When my UserStaff is deleted, I don't want anything to happen to User. I understand that this is a cascading relationship, but I'm not sure which way.
i.e. Do I select the existing foreign key in my UserStaff table and make it cascading, or do I create a new foreign key in User and set that to cascading?
Yes, it's possible. You should make the FK in UserStaff table. In this way:
User Table
CREATE TABLE `User` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
UserStaff Table
CREATE TABLE `UserStaff` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`UserId` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`Id`),
KEY `UserId` (`UserId`),
CONSTRAINT `UserStaff_ibfk_1`
FOREIGN KEY (`UserId`)
REFERENCES `User` (`Id`)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
From Wikipedia:
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]).
Here, User is the master table, and UserStaff is the child table. So, yes, you'll want to create the foreign key in UserStaff, with ON DELETE CASCADE
It's been a while since I've used this, but here goes (btw, I use Toad for MySql - a great IDE, and it's free too - http://www.toadworld.com/Freeware/ToadforMySQLFreeware/tabid/561/Default.aspx!)
You need to add a Constraint to the User table. If you have an id column (and the corresponding foreign userid key in UserStaff) then the SouceColumn should be id, the destination table UserStaff and the destination column userid. You can then set the OnDelete action to be 'Cascade'
The other options are pretty self-explanatory - Restrict limits values to the values in the source column, Set Null sets the foreign key matches to Null and No Action does, er, nothing.
This stuff is very easy to do via the Toad IDE. I used MySqlAdmin tools for ages but recently discovered Toad (and it has diff and compare tools too!).
The ON DELETE CASCADE is specified on the foreign key in the UserStaff table. For additional info on foreign keys the MySQL documentation has a number of examples. The User table does not have a foreign key pointing to UserStaff, so it will not be affected by changes to the UserStaff table.
The easiest way might be to make two quick tables and try it out. But since you didn't I can tell you that the outcome will be that it work the way that you want to.
When you have a table User and a table UserStaff were a field in UserStaff uses a foreign key to reference a field in User; then if you delete a record from UserStaff that will be removed wihtout having any affect on the User table. The other way around will delete all records related to that record.
Short version: A field in UserStaff should reference a field in User with CASCADE