Example: I have category table with the FOREIGN KEY to the same table:
CREATE TABLE `categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(250) COLLATE utf8_unicode_ci NOT NULL,
`parent_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `categories_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `categories` (`id`)
)
How to constraint the parent_id that it can't be the child parent_id.
Example:
we have a parent's row where parent_id equal child's id:
['1', 'parent_name', '**2**']
Child row:
['2', 'child_name', '**1**']
How to fix this by MySQL?
It already does not happen during insert (base on the defination of the table), you have foreign key on parent_id to id your example is a paradox, but it may happen during update of the table so you need to create a trigger for Update to prevent updating the table such as the example also For this case The CHECK constraint does not work, as I mentioned one way is to use a trigger for before update:
CREATE TRIGGER trigger_categories
BEFORE Update
ON categories FOR EACH ROW
BEGIN
DECLARE msg VARCHAR(255);
IF EXISTS (select * from categories c where c.id=NEW.parent_id and c.parent_id=NEW.id) THEN
set msg = "DIE: you can not make a parent of chield as it's chield...";
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
// also you can make NEW as NULL for preventing update under mentioned condition
END IF;
END;
Related
Assuming I am inserting rows in a MySQL table with a constraint
CREATE TABLE `parent` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
;
CREATE TABLE `child` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`id_parent` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_parent_child` (`id_parent`),
CONSTRAINT `FK_parent_child` FOREIGN KEY (`id_parent`) REFERENCES `parent` (`id`),
)
ENGINE=InnoDB
;
Then when I do an insert in the child table without the entry in the parent table:
INSERT INTO child (id, id_parent) VALUES (1, 1);
I get the following error:
Cannot add or update a child row: a foreign key constraint fails (`...`.`child`, CONSTRAINT `FK_parent_child` FOREIGN KEY (`id_parent`) REFERENCES `parent` (`id`))`
But is there a way to retrieve the value of the insert-failed row, aka 1 here? Because when I insert thousands of rows at the same time, it would be very useful to get the failed one.
I would like a fully-MySQL way, but a PHP way would work too in my case.
see table for example
CREATE TABLE parent (
id serial not null,
CONSTRAINT parent_pkey PRIMARY KEY (id)
);
CREATE TABLE child (
id serial not null,
parent_id serial not null,
username` varchar(90) NOT NULL
CONSTRAINT child_pkey PRIMARY KEY (id),
CONSTRAINT parent_fk FOREIGN KEY (parent_id)
REFERENCES parent (id)
ON DELETE RESTRICT
ON UPDATE RESTRICT
);
is there anyway i can update the username in child table? if yes how can i update it with php code.
if no what is the other option?
UPDATE `child` SET `username` = '$username' WHERE id = '$id'
replace $username and $id with your desired values.
I have an adjacency table with parent and child elements and when I delete my parent element I would like to delete all his child.
My table:
id name parent
1 Name1 null
2 SubName1 1
When I'm trying to delete row with id=1 I would like to delete and id=2
How can I do this?
My table:
CREATE TABLE IF NOT EXISTS `cats` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`parent` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `parent` (`parent`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
Foreign keys could be the solution.
How you create them is dependent on your used Database.
At foreign keys there is a primary key defined which is like a "parent", if the parent gets deleted the childs get deleted to if you define it.
First Table:
CREATE TABLE Portfolio_Categories
(
cat_id int(11) NOT NULL,
cat_title varchar(255) NOT NULL,
cat_dir varchar(255) NOT NULL
)
ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;
Second Table:
CREATE TABLE Portfolio_Images
(
img_id int(11) NOT NULL,
cat_id int(11) NOT NULL,
img varchar(255) NOT NULL,
img_title varchar(255) DEFAULT NULL
)
ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=latin1 COMMENT='Table to store the Portfolio Images';
Constraints:
ALTER TABLE Portfolio_Categories
ADD PRIMARY KEY (cat_id);
ALTER TABLE Portfolio_Images
ADD PRIMARY KEY (img_id), ADD KEY cat_id (cat_id), ADD KEY img_id (img_id);
ALTER TABLE Portfolio_Images ADD CONSTRAINT cat_id FOREIGN KEY
(cat_id) REFERENCES Portfolio_Categories (cat_id);
My PHP Code:
$query = "UPDATE
Portfolio_Images
SET
Portfolio_Images.img = :new_img,
Portfolio_Images.img_title = :new_tit,
Portfolio_Images.cat_id =
(SELECT t_cat.cat_id FROM (SELECT * FROM Portfolio_Categories) AS t_cat WHERE t_cat.cat_title = :new_cat)
WHERE
Portfolio_Images.img = :old_img;";
$stmt = $_MySQLConn->prepare($query);
$stmt->bindParam(':new_img', $new_img);
$stmt->bindParam(':new_tit', $new_tit);
$stmt->bindParam(':new_cat', $new_cat);
$stmt->bindParam(':old_img', $old_img);
if($stmt->execute())
{
$return_value = array('success'=>true,
'new_img:'=>$new_img,
'new_tit'=>$new_tit,
'new_cat'=>$new_cat,
'old_img'=>$old_img);
}
else
{
$return_value = array('success'=>false,'error_code'=>'Could not execute query');
}
What should it do:
It should update my table without any error (as it does if I run the statement directly)
What does it do:
PHP shows me this error message:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a child row: a foreign key constraint fails
(1_new.Portfolio_Images, CONSTRAINT cat_id FOREIGN KEY
(cat_id) REFERENCES Portfolio_Categories (cat_id))
This means that you are inserting a row in Portfolio_Images where the value in Portfolio_Images.cat_id does not exist in Portfolio_Categories.cat_id.
In other words, if in Portfolio_Categories.cat_id you only have the values 1, 2, 4 you can only insert in Portfolio_Images.cat_id the values 1, 2 or 4.
I'm curious to know if there's away to tell which columns have been set to CASCADE using mysql. Doing DESC TABLE; doesn't appear to produce anything obvious. Any suggestions?
Since MySQL 5.1.10, you can obtain this information from the INFORMATION_SCHEMA tables by joining REFERENTIAL_CONSTRAINTS to KEY_COLUMN_USAGE:
SELECT kcu.COLUMN_NAME
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
USING (CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME)
WHERE 'CASCADE' IN (rc.DELETE_RULE, rc.UPDATE_RULE)
AND kcu.TABLE_SCHEMA = DATABASE()
AND kcu.TABLE_NAME = 'my_table'
You can use the:
show create table tableName;
which will output a create table that has the references to cascading deletes.
Example snagged from the docs:
mysql> SHOW CREATE TABLE ibtest11c\G
*************************** 1. row ***************************
Table: ibtest11c
Create Table: CREATE TABLE `ibtest11c` (
`A` int(11) NOT NULL auto_increment,
`D` int(11) NOT NULL default '0',
`B` varchar(200) NOT NULL default '',
`C` varchar(175) default NULL,
PRIMARY KEY (`A`,`D`,`B`),
KEY `B` (`B`,`C`),
KEY `C` (`C`),
CONSTRAINT `0_38775` FOREIGN KEY (`A`, `D`)
REFERENCES `ibtest11a` (`A`, `D`)
ON DELETE CASCADE ON UPDATE CASCADE, // <--- This is what you are looking for
CONSTRAINT `0_38776` FOREIGN KEY (`B`, `C`)
REFERENCES `ibtest11a` (`B`, `C`) // <--- This is what you are looking for
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=INNODB CHARSET=latin1
1 row in set (0.01 sec)