FOREIGN KEY references same table's column. Can't insert values - mysql

I created table with FOREIGN KEY and can't insert anything.
CREATE TABLE menus (
id int(10),
parent_id int(10),
label varchar(255),
PRIMARY KEY (id),
FOREIGN KEY (parent_id) REFERENCES menus (id)
);
I need FOREIGN KEY to automatically delete children when parent was deleted. This table was successfully created but I can't insert anything.
INSERT INTO `menus` (`parent_id`, `label`)
VALUES ('1', 'label1');
or
INSERT INTO `menus` (`label`)
VALUES ( 'label1');
#1452 - Cannot add or update a child row: a foreign key constraint fails
I really don't want look for any children in php code so I need somehow create simple table with 3 columns and automatically drop all children and they children too.

For all your needs you should take this structure
CREATE TABLE `menus` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`parent_id` int(11) unsigned DEFAULT NULL,
`label` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `fk_parent_menu` (`parent_id`),
CONSTRAINT `fk_parent_menu` FOREIGN KEY (`parent_id`)
REFERENCES `menus` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
);
SQL Fiddle DEMO
Demo shows inserting and deleting of a parent node
The magic drop part for all children is done by ON DELETE CASCADE

Typically, you will need to allow the 'root' record to have a null parent - i.e. menus.parent_id should be nullable, and the 'root' menu item will have a null parent_id.
i.e.
Change your DDL to:
parent_id int(10) NULL
And then you add your root element with NULL as the parent_id
insert into `menus` (id, `label`, parent_id)
VALUES (1, 'label1', null);
Then you are good to go with child elements:
insert into `menus` (id, `label`, parent_id)
VALUES (2, 'subitem1', 1);
etc.
SQL Fiddle here

Related

Create a categorical column in sql

I need to create a table with this following relational schema.
The relational schema for this the new table is as follows:
The foreign keys for this new table are as follows:
Transit.{package, departDistributionCentre, departTimestamp}
references Depart.{package, distributionCentre, timestamp}
Transit.{package, arriveDistributionCentre, arriveTimestamp}
references Arrive.{package, distributionCentre, timestamp}
The table that i want to create is named Transit, with a particular column value must be one of this {“Plane”, “Car”, “Truck”}.
This is the code that i create, but apparently, the requirement to answer this question is not allowing me to insert values into table.
CREATE TABLE DeliveryMethod (
MethodCode INT NOT NULL,
Description VARCHAR(50),
PRIMARY KEY (MethodCode)
);
INSERT INTO DeliveryMethod (MethodCode, Description) VALUES (1, "Plane"), (2, "Car"), (3, "Truck");
CREATE TABLE Transit (
package VARCHAR(10) NOT NULL,
departDistributionCentre VARCHAR(100) NOT NULL,
departTimestamp TIMESTAMP NOT NULL,
arriveDistributionCentre VARCHAR(100) NOT NULL,
arriveTimestamp TIMESTAMP NOT NULL,
method INT NOT NULL,
cost INT,
PRIMARY KEY (package, departDistributionCentre, departTimestamp, arriveDistributionCentre, arriveTimestamp),
CONSTRAINT method_fk FOREIGN KEY (method) REFERENCES DeliveryMethod(MethodCode) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT depart_fk FOREIGN KEY (package, departDistributionCentre, departTimestamp) REFERENCES Depart(package, distributionCentre, timestamp) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT arrive_fk FOREIGN KEY (package, arriveDistributionCentre, arriveTimestamp) REFERENCES Arrive(package, distributionCentre, timestamp) ON DELETE RESTRICT ON UPDATE CASCADE
);
any of you good people have a lead to solve this without inserting values to a table as reference?
Thanks

How to avoid MySQL composite primary key permutations?

CREATE TABLE Friends_Relations(
buddy_id VARCHAR(255) NOT NULL,
mate_id VARCHAR(255) NOT NULL,
PRIMARY KEY (buddy_id, mate_id),
FOREIGN KEY (buddy_id) REFERENCES Users(id) ON DELETE CASCADE,
FOREIGN KEY (mate_id) REFERENCES Users(id) ON DELETE CASCADE
);
There's this mutual friendship relation where (friend_A, friend_B) is the same as (friend_B, friend_A).
I've tried adding a unique key, but it was to no avail:
ALTER TABLE Friends_Relation ADD UNIQUE KEY (mate_id, buddy_id);
Is there a way to avoid these permutations ?
You can do:
create table friends_relations (
buddy_id varchar(255) not null,
mate_id varchar(255) not null,
constraint uq1 unique (
(least(buddy_id, mate_id)), (greatest(buddy_id, mate_id))
),
primary key (buddy_id, mate_id)
);
Then if it won't accept symmetric rows:
insert into friends_relations (buddy_id, mate_id) values (456, 123);
insert into friends_relations (buddy_id, mate_id) values (123, 456); -- fails
See running example at db<>fiddle.
There's also another trick. What you can alternatively do is to enforce buddy_id < mate_id. This, however, will restrict the way you insert data. For example you can do:
CREATE TABLE Friends_Relations (
buddy_id VARCHAR(255) NOT NULL,
mate_id VARCHAR(255) NOT NULL,
PRIMARY KEY (buddy_id, mate_id),
FOREIGN KEY (buddy_id) REFERENCES Users(id) ON DELETE CASCADE,
FOREIGN KEY (mate_id) REFERENCES Users(id) ON DELETE CASCADE,
constraint ck1 CHECK (buddy_id < mate_id) -- added constraint
);
Then, when you insert:
insert into Friends_Relations (buddy_id, mate_id) values (123, 456); -- succeeds
insert into Friends_Relations (buddy_id, mate_id) values (456, 123); -- fails
from this dba exchange question
ALTER TABLE Friends_Relation ADD UNIQUE KEY
((least(buddy_id,mate_id)), (greatest(buddy_id,mate_id)))
This allows the pair in either order, but still only once.

Using foreign key in the same table

I created a table inside my database named categories:
CREATE TABLE IF NOT EXISTS `category`
( `categoryName` varchar(128) ,
`subcategoryName` varchar(128) ,
PRIMARY KEY (`categoryName`) )
ENGINE=InnoDB DEFAULT CHARSET=latin1
A category in this table may be a subcategory of another category in this field.So,subcategory is a FK to categories.Initialiasiation:
ALTER TABLE `category` ADD FOREIGN KEY (`subcategoryName`)
REFERENCES `category`(`categoryName`) ON DELETE RESTRICT ON UPDATE RESTRICT;
So i tried inserting values in this table like this:
INSERT INTO `category` (`categoryName`, `subcategoryName`) VALUES
( 'Literature','Satire'),
( 'Science','Mathematics'),
( 'Science','Physics');
but i get this error:
#1452 - Cannot add or update a child row: a foreign key constraint fails (`php_beginner_crud_level_1`.`category`, CONSTRAINT `category_ibfk_1` FOREIGN KEY (`subcategoryName`) REFERENCES `category` (`categoryName`))
I think this means that i can't isent a subcategory if the category does not already exist.So what i did is insert first single categories:
INSERT INTO `category` (`categoryName`) VALUES
( 'Literature'),
( 'Mathematics'),
( 'Programming');
Hw can i insert subcategories for these categories now?
for example if i want a subcategory: Java for Programming how can i insert it into the table?
You have the foreign key relationship backwards. Subcategories reference categories, so it should be:
ALTER TABLE `category` ADD FOREIGN KEY (`categoryName`)
REFERENCES `category`(`subcategoryName`) ON DELETE RESTRICT ON UPDATE RESTRICT;
And the primary key should be subcategoryName, not categoryName.
You need to create subcategories with no category for the top-level categories in the hierarchy.
INSERT INTO `category` (`categoryName`, `subcategoryName`) VALUES
(NULL, 'Literature'),
(NULL, 'Science'),
( 'Literature','Satire'),
( 'Science','Mathematics'),
( 'Physics','Science');
Or rename things to make more sense.
CREATE TABLE IF NOT EXISTS `category`
( `categoryName` varchar(128) NOT NULL,
`supercategoryName` varchar(128) ,
PRIMARY KEY (`categoryName`) )
ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `category` ADD FOREIGN KEY (`supercategoryName`)
REFERENCES `category`(`categoryName`) ON DELETE RESTRICT ON UPDATE RESTRICT;
INSERT INTO `category` (`categoryName`, `subcategoryName`) VALUES
(NULL, 'Literature'),
(NULL, 'Science'),
('Literature', NULL),
('Science', NULL),
( 'Satire','Literature'),
( 'Mathematics','Science'),
( 'Science'',Physics');

Why can't I drop a foreign key?

Scenario:
Parent table | id primary key, message_p
Child table | id primary key, parent_id foreign key, message_c
I had 1 row of data in the parent table and 2 rows of data in the child table. I wanted to test constraints that an FK relationship enforces. I then attempted to remove the foreign key from the child table so that evene though the child table had 2 rows, I could then go ahead and remove the parent row:
alter table child
drop foreign key parent_id
I then got the following error:
[1091 - Can't DROP 'parent_id'; check that column/key exists]
Notes:
show create table child
CREATE TABLE `track` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`member_id` int(11) NOT NULL,
`title` varchar(50) DEFAULT NULL,
`artist` varchar(50) DEFAULT 'TBA',
`album` varchar(50) DEFAULT 'TBA',
`genre` varchar(50) DEFAULT 'TBA',
`dance_style` varchar(50) DEFAULT 'TBA',
PRIMARY KEY (`id`),
KEY `member_id` (`member_id`),
CONSTRAINT `track_ibfk_1` FOREIGN KEY (`member_id`) REFERENCES `member` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Am I missing something in my query or the general understanding about FK's?
You are trying to delete the Foreign Key Constraint by column name, that's why your code doesn't work.
First query your foreign key constraint name (using show create table child as you did show the key name, something like track_ibfk_1
If you tried out everything as commented (assuming correct table names, constraint names, ...), I see no reason why it should not work.
If you have, however, other tables that hold foreign keys to parent (or 'member'), maybe that these constraints block removal of parent entries?
Anyway, here is an example showing that dropping a foreign key actually works:
drop table if exists testchild;
drop table if exists test;
create table test(
id int primary key,
name varchar(50)
);
create table testchild(
childid int primary key,
reftotest int,
constraint reftotest_FK foreign key (reftotest) references test(id)
);
insert into test values (1, 'Jack'), (2, 'Sam');
insert into testchild values (1, 1), (2, 2), (3, 1);
insert into testchild values (4,5); # will fail
delete from test where id = 1; # will fail
alter table testchild drop foreign key reftotest_FK;
insert into testchild values (4,5); # will not fail any more
delete from test where id = 1; # will not fail any more

ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails

When I execute the following SQL command:
INSERT INTO test_usershosts (RID,userid,hid,Usr,Pass)
VALUES (NULL,1,1,"user","pass");
I'm getting the following error message:
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint f
ails (`dm`.`test_usershosts`, CONSTRAINT `test_usershosts_ibfk_1` FOREIGN KEY (`
userid`) REFERENCES `test_users` (`userid`) ON DELETE CASCADE ON UPDATE CASCADE)
My tables:
CREATE TABLE IF NOT EXISTS `test_users` (
`userid` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(10) NOT NULL DEFAULT '',
`password` varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (userid)
) ENGINE=InnoDB;
INSERT INTO `test_users` (`userid`, `username`, `password) VALUES
(1120, 'guest', '12250170a9624f336ca24');
CREATE TABLE IF NOT EXISTS `test_hosts` (
`hid` int(11) NOT NULL AUTO_INCREMENT,
`UID` int(11) NOT NULL,
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (hid)
) ENGINE=InnoDB;
INSERT INTO `test_hosts` (`hid`, `UID`, `name`) VALUES (30, 10, 'MU');
CREATE TABLE IF NOT EXISTS `test_usershosts` (
`RID` int(11) NULL AUTO_INCREMENT,
`userid` int(11) ,
`hid` int(11) ,
`Usr` varchar(100) ,
`Pass` varchar(100) ,
PRIMARY KEY (RID),
INDEX (userid),
INDEX (hid),
FOREIGN KEY (userid) REFERENCES test_users (userid)
ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (hid) REFERENCES test_hosts (hid)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;
I've looked into many similar cases, but couldn't find any solution. Any help would be appreciated.
The reason why you are getting that exception is because you are inserting a record on table test_usershosts which the value of the userID is not present on table test_users. Same as the value of hid is not also present on table test_hosts.
Table test_usershosts is dependent on tables: test_users and test_hosts. So be sure that when inserting records on table test_usershosts, the values for hid and userid already exists on the parent tables: test_users and test_hosts.
Try executing this query and surely it will be inserted.
INSERT INTO test_usershosts (RID,userid,hid,Usr,Pass)
VALUES (NULL,1120,30,'user','pass');
SQLFiddle Demo
I see that AUTO_INCREMENT option on tables: test_users and test_hosts, are not needed since you are supplying values on every query you are executing on the two tables.
In test_users guest's UserID is 1120 and
in test_hosts hid = 30
you must change
INSERT INTO test_usershosts (RID,userid,hid,Usr,Pass) VALUES (NULL,1,1,"user","pass");
to:
INSERT INTO test_usershosts (RID,userid,hid,Usr,Pass) VALUES (NULL,1120,30,"user","pass");
in my case in case it serves someone.
I was struggling to find the solution what usually happens when making a primary key is also marked as unique.
but in my case it was only marked as primary and it was not marked as unique, until I noticed that the option of unica was "open" and I clicked it, until then I let myself make the relationship.
Then for the record ... check that your primary keys are also unique.