Cannot insert into table with stored generated primary key - mysql

I cannot insert data in table with generated stored primary key.
My table is:
CREATE TABLE `living_complex` (
`id` bigint(32) GENERATED ALWAYS AS (`location_id`) STORED NOT NULL,
`location_id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unq_living_complex_name` (`name`),
KEY `idx_living_complex_location_id` (`location_id`),
KEY `idx_living_complex_name` (`name`),
CONSTRAINT `fk_living_complex_location_id` FOREIGN KEY (`location_id`) REFERENCES `location` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
My insert statement:
INSERT INTO `reeve`.`living_complex` (`location_id`, `name`)
VALUES ('1', 'some_living_complex');
Error is:
1048: Column 'id' cannot be null
I don't have NOT NULL key-word in create statement. Why does it asks for id?

Got it. There was an mistake in trigger
CREATE DEFINER=`root`#`localhost` TRIGGER `reeve`.`trg_living_complex_object_id` BEFORE INSERT ON `living_complex` FOR EACH ROW
BEGIN
INSERT INTO `reeve`.`object` (
`id`,
`object_type_id`
)
VALUES (
new.id,
(SELECT `object_type`.`id` FROM `reeve`.`object_type` WHERE `table_name` = 'living_complex')
);
END
Which should be AFTER insert. Because I don't have NEW.id (generated by expression) until I do insert.

Related

MySQL cascade update failed when foreign key column referenced in composite primary key

Unlike the similar other questions, I get error #1452 when updating the parent row. Why does it happen? Thank you in advance.
Here are the relevant tables:
CREATE TABLE IF NOT EXISTS `user`
(
`username` VARCHAR(100) NOT NULL,
`password` VARCHAR(200) NOT NULL,
`name` VARCHAR(100),
`surname` VARCHAR(100),
`icon` BLOB,
PRIMARY KEY (username)
);
CREATE TABLE IF NOT EXISTS `document`
(
`owner` VARCHAR(100) NOT NULL,
`name` VARCHAR(100) NOT NULL,
`sharing_link` VARCHAR(200) UNIQUE NOT NULL,
PRIMARY KEY (`owner`, `name`),
FOREIGN KEY (`owner`) REFERENCES user(`username`) ON UPDATE CASCADE
);
CREATE TABLE IF NOT EXISTS sharing
(
`sharing_user` VARCHAR(100) NOT NULL,
`document_owner` VARCHAR(100) NOT NULL,
`document_name` VARCHAR(100) NOT NULL,
PRIMARY KEY (`sharing_user`, `document_owner`, `document_name`),
FOREIGN KEY (`sharing_user`) REFERENCES user(`username`) ON UPDATE CASCADE,
FOREIGN KEY (`document_owner`, `document_name`) REFERENCES `document`(`owner`, `name`) ON UPDATE CASCADE
);
And here how to reproduce the error:
INSERT INTO `user` (`username`, `password`, `name`, `surname`, `icon`) VALUES ('fruggeri', 'fruggeri', 'Franco', 'Ruggeri', NULL);
INSERT INTO `document` (`owner`, `name`, `sharing_link`) VALUES ('fruggeri', 'document', 'sharing_link');
INSERT INTO `sharing` (`sharing_user`, `document_owner`, `document_name`) VALUES ('fruggeri', 'fruggeri', 'document');
UPDATE `user` SET `username` = 'new_fruggeri' WHERE `user`.`username` = 'fruggeri'
Resulting error:
#1452 - Cannot add or update a child row: a foreign key constraint fails (`collaborative_text_editor`.`sharing`, CONSTRAINT `sharing_ibfk_1` FOREIGN KEY (`sharing_user`) REFERENCES `user` (`username`) ON UPDATE CASCADE)

MySql composite foreign key ON DELETE set null [duplicate]

This question already has an answer here:
Multiple Column Foreign Key: Set single column to Null "ON DELETE" instead of all
(1 answer)
Closed 2 years ago.
Please refer to this SQLFiddle
CREATE TABLE `parent` (
`id` varchar(64) NOT NULL,
`master_id` varchar(64) NOT NULL,
`c1_id` varchar(64) DEFAULT NULL,
`c2_id` varchar(64) DEFAULT NULL,
PRIMARY KEY (`master_id`, `id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `child_1` (
`id` varchar(64) NOT NULL,
`master_id` varchar(64) NOT NULL,
PRIMARY KEY (`master_id`, `id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `child_2` (
`id` varchar(64) NOT NULL,
`master_id` varchar(64) NOT NULL,
PRIMARY KEY (`master_id`, `id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO child_1 (`id`, `master_id`)
VALUES
(1, 'm1');
INSERT INTO child_2 (`id`, `master_id`)
VALUES
(2, 'm2'),
(3, 'm1');
INSERT INTO parent (`id`, `master_id`, `c1_id`, `c2_id`)
VALUES
(4, 'm1', null, null),
(5, 'm1', 1, null),
(6, 'm2', null, 2);
I have multiple tables that have composite Primary Key.
All PK are PRIMARY KEY (master_id, id)
And now I try to add Foreign Keys to these tables.
ALTER TABLE `parent`
ADD CONSTRAINT parent_fk_1
FOREIGN KEY (`master_id`, `c1_id`)
REFERENCES child_1 (`master_id`, `id`)
ON UPDATE CASCADE
ON DELETE SET NULL;
But it throws error Cannot add foreign key constraint.
Here parent.master_id always must stay NOT NULL while c1_id and c2_id can be set to NULL.
Is it possible to achieve this kind of Foreign Key setup?
I found that there is MATCH SIMPLE option that allows composite key to be partial NULL, but how to apply it for ON DELETE SET NULL?
Both referring Column are NOT NULL, so you can't use ON DELETE SET NULL, this violates the NOT NULL
ALTER TABLE `parent`
ADD CONSTRAINT parent_fk_1
FOREIGN KEY (`master_id`, `c1_id`)
REFERENCES child_1 (`master_id`, `id`)
ON UPDATE CASCADE;

MySQL trigger insert after insert into another table

I want to add a foreign key into tblprowareinventory whenever I insert into tblprowareproducts:
tblProwareproducts
CREATE TABLE `tblprowareproducts` (
`ItemID` int(11) NOT NULL,
`ItemCode` varchar(30) NOT NULL,
`itemDescription` varchar(60) NOT NULL,
`Strand` varchar(30) NOT NULL,
`UnitCost` double NOT NULL,
`SaleCost` double NOT NULL,
`CategoryID_fk` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `tblprowareproducts`
ADD PRIMARY KEY (`ItemID`),
ADD KEY `CategoryID_fk` (`CategoryID_fk`);
ALTER TABLE `tblprowareproducts`
MODIFY `ItemID` int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE `tblprowareproducts`
ADD CONSTRAINT `tblprowareproducts_ibfk_1` FOREIGN KEY (`CategoryID_fk`) REFERENCES `tblprowarecategory` (`PCategoryID`) ON DELETE CASCADE ON UPDATE CASCADE;
COMMIT;
tblProwareinventory
CREATE TABLE `tblprowareinventory` (
`inventoryID` int(11) NOT NULL,
`ItemID_FK` int(11) NOT NULL,
`DateOfInventory` date NOT NULL,
`CurrentQuantity` int(11) NOT NULL,
`TotalQuantity` int(11) NOT NULL,
`DeliveredQuantity` int(11) NOT NULL,
`PhysicalCount` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `tblprowareinventory`
ADD PRIMARY KEY (`inventoryID`),
ADD KEY `ItemID_FK` (`ItemID_FK`);
ALTER TABLE `tblprowareinventory`
ADD CONSTRAINT `tblprowareinventory_ibfk_2` FOREIGN KEY (`ItemID_FK`) REFERENCES `tblprowareproducts` (`ItemID`) ON DELETE CASCADE ON UPDATE CASCADE;
COMMIT;
INSERT INTO tblprowareinventory(ItemID_FK)
VALUES ((SELECT ItemID FROM tblprowareproducts))
but I get this error:
You can use the following CREATE TRIGGER statement:
DELIMITER //
CREATE DEFINER = `root`#`localhost` TRIGGER AddToInventory AFTER INSERT ON tblprowareproducts
FOR EACH ROW
BEGIN
INSERT INTO tblprowareinventory (ItemID_FK) VALUES (NEW.ItemID);
END;//
DELIMITER ;
Note: You have to remove your current trigger on phpMyAdmin or with the following statement: DROP TRIGGER AddToInventory; to successfully run this CREATE TRIGGER statement.
The TRIGGER successfully add a new row to the tblprowareinventory table with the NEW.ItemID, but you defined a PRIMARY KEY on the inventoryID of tblprowareinventory table. That's OK, but after trying INSERT a second row on tblprowareinventory table, you should get an error:
#1062 - Duplicate entry '0' for key 'PRIMARY'
The TRIGGER tries to INSERT a second row on tblprowareinventory table with 0 on the inventoryID column. This is not possible because 0 can only exists once on the inventoryID column.
You can solve this issue using a AUTO_INCREMENT on the inventoryID column too:
ALTER TABLE `tblprowareinventory` MODIFY `inventoryID` INT(11) NOT NULL AUTO_INCREMENT;
To INSERT a new row on tblprowareproducts table I used the following statement:
INSERT INTO `tblprowareproducts` (`ItemID`, `ItemCode`, `itemDescription`, `Strand`, `UnitCost`, `SaleCost`, `CategoryID_fk`)
VALUES (NULL, '111', '111', '111', '1', '1', '1')

How to make all the inserts and THEN check the foreign key constraints? (SQL transaction fails with foreign key constraint)

I have two tables:
Each deck (of cards) always belongs to some player (one player can have 1..* decks). Moreover, each player always has one (and one only) active deck.
I want to add a new player, but if I just execute INSERT INTO players(...) VALUES (...), I won't have the active_deck_id that should be inserted in this query. The same way, if I start from decks, I won't have player_id.
That's why I decided to use the transaction (within a procedure):
CREATE PROCEDURE `add_player` (IN login VARCHAR(255), IN password VARCHAR(255),
OUT player_id INT(11))
BEGIN
START TRANSACTION;
INSERT INTO `players` (id, `login`, `password`, registered, last_logged, active_deck_id)
VALUES ('', login, pass, now(), now(), 0);
SET player_id = LAST_INSERT_ID();
INSERT INTO `decks` (id, name, player_id) VALUES ('', `sample deck`, player_id);
COMMIT;
END
END
Then I've just called it with:
set #login = 'mylogin';
set #pass = 'pass';
call add_player(#login, #pass, #id);
... but I got an error:
#1452 - Cannot add or update a child row: a foreign key constraint fails (`game`.`players`, CONSTRAINT `active_deck` FOREIGN KEY (`active_deck_id`) REFERENCES `decks` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
So, how to make all the inserts and THEN check the foreign key constraints? Because after first insert the constraints are supposed to be broken, but after the whole transaction they should be ok.
The SQL for my tables:
CREATE TABLE IF NOT EXISTS `game`.`decks` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`player_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id`, `player_id`),
INDEX `player` (`player_id` ASC),
CONSTRAINT `player`
FOREIGN KEY (`player_id`)
REFERENCES `game`.`players` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `game`.`players` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`login` VARCHAR(255) NOT NULL,
`password` VARCHAR(255) NOT NULL,
`registered` DATETIME NOT NULL,
`last_logged` DATETIME NOT NULL,
`active_deck_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
INDEX `active_deck` (`active_deck_id` ASC),
CONSTRAINT `active_deck`
FOREIGN KEY (`active_deck_id`)
REFERENCES `game`.`decks` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
Try this command
SET FOREIGN_KEY_CHECKS = 0;
before you make your inserts, then turn it on by setting the value to 1.

Insert in to child table that have foreign key to an auto_increment column

Schema is as shown below
CREATE TABLE `country` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`country_name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
CREATE TABLE `state_table` (
`id` int(11),
`state_name` varchar(45) DEFAULT NULL,
`country_id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`country_id`),
CONSTRAINT `country_fk` FOREIGN KEY (`country_id`)
REFERENCES `country` (`id`) ON DELETE CASCADE on update cascade
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='';
When I tried to insert data into both tables, data is inserting in to parent table but it is not inserting in to child table and error here is
Schema Creation Failed: Cannot add or update a child row: a foreign key constraint fails (`db_2_3b712`.`state_table`, CONSTRAINT `country_fk` FOREIGN KEY (`country_id`) REFERENCES `country` (`id`) ON DELETE CASCADE ON UPDATE CASCADE):
As per my idea having country_id as auto_increment is creating problem.
I tried inserting like this
INSERT INTO country (country_name) VALUES ('US of A');
INSERT INTO state_table (state_name,id) VALUES
('Minnesota', 2),
('Arizona', 2);
Help me.
The id that you are inserting must exist in country table and has to be a valid id of a country.
Propably there is no country with id=2.
You can get the inserted id using function mysql_insert_id()
So it'd look like this:
INSERT INTO country (country_name) VALUES ('US of A');
INSERT INTO state_table (state_name,id) VALUES
('Minnesota', mysql_insert_id()),
('Arizona', mysql_insert_id());
Or even better you could assign this id to a variable and insert that.
INSERT INTO country (country_name) VALUES ('US of A');
$id = mysql_insert_id();
INSERT INTO state_table (state_name,id) VALUES
('Minnesota', $id),
('Arizona', $id);
Why do you have AUTO_INCREMENT to a foreign key constrained column? Delete AUTO_INCREMENT from country_id column and try again.