MySQL foreign key constraint error on insert in transaction - mysql

I have this error when inserting values into an association table during transaction:
Cannot add or update a child row: a foreign key constraint fails (dev.genre, CONSTRAINT fk_Genre_EntityType1 FOREIGN KEY (idEntityType) REFERENCES entitytype (idEntityType) ON DELETE NO ACTION ON UPDATE NO ACTION)
Here is the part of the schema that describes the tables used:
and here is the create statement of the genre table:
-- -----------------------------------------------------
-- Table `dev`.`Genre`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `dev`.`Genre` (
`idGenre` INT NOT NULL ,
`Name` VARCHAR(45) NULL COMMENT 'musique, spectacle, expo' ,
`idEntityType` INT NOT NULL ,
`idStyle` INT NOT NULL ,
PRIMARY KEY (`idGenre`, `idEntityType`, `idStyle`) ,
INDEX `fk_Genre_EntityType1_idx` (`idEntityType` ASC) ,
INDEX `fk_Genre_Style1_idx` (`idStyle` ASC) ,
CONSTRAINT `fk_Genre_EntityType1`
FOREIGN KEY (`idEntityType` )
REFERENCES `dev`.`EntityType` (`idEntityType` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Genre_Style1`
FOREIGN KEY (`idStyle` )
REFERENCES `dev`.`Style` (`idStyle` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
To resume, the Genre tables references EntityType and Style, that's all.
The error occurs when I try to create a new Style and then add an association in the Genre table.
Everything is within a transaction, and what I do is:
create the new style in the Style table
get the id of the created style
insert an association in the genre table, and that's when I get the error.
I've searched quite a while on the web, but the only thing I found was this SO post: In MySQL, can I defer referential integrity checks until commit
I'm not sure this is what it is about here, because the error happens on a table that hadn't changed during the transaction (EntityType). Or am I missing something?
Can someone explain me the reason why I have this error please? (I'm stuck here)
Also, if it really have something to do with the SO post I mentioned earlier, is there a "clean" way of doing that kind of inserts without writing my own rollback mechanism?
Thanks for your answers
EDIT
the first query to insert a new style is:
CREATE PROCEDURE `Entity_CreateStyle`
(
IN p_name varchar(45),
OUT op_idStyle int(11)
)
BEGIN
insert into Style(idParentStyle, Name, IsValidated)
values(null, p_name, 0);
SET op_idStyle = LAST_INSERT_ID();
END
the next one, that produces the error:
CREATE PROCEDURE `Entity_AssociateStyleWithEntityType`
(
IN p_idGenre int(11),
IN p_Name varchar(45),
IN p_idEntityType int(11),
IN p_idStyle int(11)
)
BEGIN
insert into Genre(idGenre, Name, idEntityType, idStyle)
values(p_idGenre, p_Name, p_idEntityType, p_idStyle);
END
both are actually stored procedures that we call from C# using MySQL.Net connector
the p_idEntityType comes from the model (MVC) and I checked it's value is correct and exists in EntityType table.

The error message is clear: entitytype is referenced by genre. This means that ALL rows in entitytype must have a match in genre, or can't be inserted. There is a match when genre.entitytype = entitytype.entitytype.

Related

Struggling to figure out a syntax error for a MySQL create table statement in regards to a foreign key reference

I've been wracking my brain for quite a while trying to figure out what is wrong with the first foreign key reference in the Property create table statement below. To isolate the error, I attempted to delete the foreign key reference and just create the table with the second foreign key reference in the Property table (ie: vendorId -> Vendor(vendorId)) and the table was able to be created with no issues. Thus, I believe I may have a design flaw on my hands which has me concerned. Both of the referenced tables have been created as well so that is not the issue. Help would be greatly appreciated, thanks! (Apologies if its some kind of dumb syntax error I'm not seeing)
Error is at line 11 in the Property create table statement:
error #1064 You have an error in your SQL syntax
Line 11: PRIMARY KEY (pid, vendorId),
Line 12: FOREIGN KEY (apptStatus) REFERENCES AgentSchedule(apptStatus)
Here is the code for the Property table referencing the AgentSchedule table as well as the Vendor table
CREATE TABLE Property(
pid INTEGER,
vendorId INTEGER,
houseDescr CHAR(150),
photoCopy CHAR(5),
propertyAddr CHAR(50),
apptStatus CHAR(5) DEFAULT 'False',
numVisits INTEGER,
propertyComments CHAR(150),
isEmpty CHAR(5),
PRIMARY KEY (pid, vendorId),
FOREIGN KEY (apptStatus) REFERENCES AgentSchedule(apptStatus)
ON DELETE SET DEFAULT
ON UPDATE CASCADE,
FOREIGN KEY (vendorId) REFERENCES Vendor(vendorId)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT TOF CHECK(photoCopy IN ('True','False')
AND apptStatus IN ('True', 'False')
AND isEmpty IN ('True', 'False'))
)
Here is the code for the referenced table corresponding to the first foreign key reference in the Property table.
CREATE TABLE AgentSchedule(
aid INTEGER,
propertyId INTEGER,
apptTime DATE UNIQUE,
apptStatus CHAR(5),
sickOrHolidays CHAR(5),
PRIMARY KEY (aid, propertyId),
CONSTRAINT TOF CHECK( apptStatus IN ('True', 'False')
AND sickOrHolidays IN ('True', 'False'))
)
Here is the referenced table corresponding to the second foreign key reference in the Property table.
CREATE TABLE Vendor(
vendorId INTEGER,
name CHAR(50),
phone INTEGER,
faxNum INTEGER,
PRIMARY KEY (vendorId),
CONSTRAINT PHONE CHECK(Phone >= 1000000000 AND Phone <= 9999999999
AND faxNum>= 1000000000
AND faxNum <= 9999999999)
)
Your problem is with the ON DELETE SET DEFAULT clause. Although MySQL recognises that clause, it is not allowed in table definitions. From the manual:
SET DEFAULT: This action is recognized by the MySQL parser, but both InnoDB and NDB reject table definitions containing ON DELETE SET DEFAULT or ON UPDATE SET DEFAULT clauses.
If you remove the SET DEFAULT clause the table creation works fine. Demo. If you need this functionality you can probably implement it via a ON DELETE trigger.

Cannot add foreign key constraint SQL when building schema

I'm taking a intro to database class right now. For a homework assignment I was given a piece of SQL code and told to just run some queries and give the results back. The problem is I can't even build the schema given with the code my teacher gave me. Here is this code:
CREATE TABLE emp (
name char(15),
dno int,
FOREIGN KEY (dno) REFERENCES dept(dno)
ON DELETE SET NULL
ON UPDATE CASCADE
);
CREATE TABLE dept (
dno int,
location char(30)
);
INSERT INTO emp(name,dno) VALUES
("Tom",111),
("Mary",111),
("Jack",222),
("Henry",222);
INSERT INTO dept(dno, location) VALUES
(111,"Irvine"),
(222,"LA"),
(333,"SF");
When this runs I get a error saying Cannot add foreign key constraint. I tried doing this via MySQL workbench and SQL Fiddle, both of which produce the same error. I don't really know whats wrong with the code given to me though and after looking online, couldn't seem to see anything obvious.
It may be part of the exercise for you to figure this out. However, assuming that it is not, here are important observations:
The foreign key reference should be to a primary key, and neither table has primary keys.
The table being referenced has to be defined before it can be referred to.
You can work on fixing these problems. Here is a SQL Fiddle with the right definitions.
The definition of the first table (emp) has a reference to a table that has not yeat been created (dept).You have to create first 'dept' to create a foreign key of it into another table.
Execute the queries in this order:
CREATE TABLE dept (
dno int,
location char(30)
);
CREATE TABLE emp (
name char(15),
dno int,
FOREIGN KEY (dno) REFERENCES dept(dno)
ON DELETE SET NULL
ON UPDATE CASCADE
);
INSERT INTO emp(name,dno) VALUES
("Tom",111),
("Mary",111),
("Jack",222),
("Henry",222);
INSERT INTO dept(dno, location) VALUES
(111,"Irvine"),
(222,"LA"),
(333,"SF");
try :CONSTRAINT dno_fk FOREIGN KEY (dno) REFERENCES dept(dno)
ON DELETE CASCADE

MySQL fk reference back to table...unable to insert new row

thanks for taking time to look at my thread.
I'm 'trying to' create a MySQL table for item categories with a column for the parent category in the table. I linked it back to the table as a fk and intend to insert (0) into the column value for items that have no parents.
Here is the table definition:
-- -----------------------------------------------------
-- Table `mydb`.`itemCategories`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`itemCategories` (
`itecat_id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`category` VARCHAR(60) NOT NULL ,
`parentCat` INT UNSIGNED NOT NULL ,
PRIMARY KEY (`itecat_id`) ,
UNIQUE INDEX `uniqueCat` (`category` ASC) ,
INDEX `fk_itemCategories_itemCategories1` (`parentCat` ASC) ,
CONSTRAINT `fk_itemCategories_itemCategories1`
FOREIGN KEY (`parentCat` )
REFERENCES `mydb`.`itemCategories` (`itecat_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
When I try to insert a new row, it gives the following error:
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`mydb`.`itemCategories`, CONSTRAINT `fk_itemCategories_itemCategories1` FOREIGN KEY (`parentCat`) REFERENCES `itemCategories` (`itecat_id`) ON DELETE NO ACTION)
Any help on how to fix this, or a better way to do it, would be very much appreciated.
Thanks!
0 is a value! You should use NULL as the "empty field".

MySQL Triggers - Implementation Issue

I am developing a MySQL database using Workbench. I want two send two fields from a newly created record to another table. I would then like to update the original table with newly created data from the second table. I was looking to implement this with triggers, unless there is a better way of course :) My attempt was a fail when I went to upload it(see below)
Specifically, I would like tc_Event to send the ID & tc_EventTags_ID to tc_EventTags to fill in tc_Tag_ID & tc_Event_ID. Afterwards I want the ID of tc_EventTags sent back to tc_Event to the tc_EventTags_ID field.
Thanks for any help.
-- -----------------------------------------------------
-- Table `mcontest`.`tc_EventTags`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mcontest`.`tc_EventTags` (
`ID` INT NOT NULL AUTO_INCREMENT ,
`tc_Tag_ID` INT NOT NULL ,
`tc_Event_ID` INT NOT NULL ,
PRIMARY KEY (`ID`) ,
INDEX `fk_tc_EventTags_tc_Tag1` (`tc_Tag_ID` ASC) ,
INDEX `fk_tc_EventTags_tc_Event1` (`tc_Event_ID` ASC) ,
CONSTRAINT `fk_tc_EventTags_tc_Tag1`
FOREIGN KEY (`tc_Tag_ID` )
REFERENCES `mcontest`.`tc_Tag` (`ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_tc_EventTags_tc_Event1`
FOREIGN KEY (`tc_Event_ID` )
REFERENCES `mcontest`.`tc_Event` (`ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = MyISAM;
-- -----------------------------------------------------
-- Table `mcontest`.`tc_Event`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mcontest`.`tc_Event` (
`ID` INT NOT NULL AUTO_INCREMENT ,
`date` DATE NOT NULL ,
`time` TIME NOT NULL ,
`location` VARCHAR(45) NOT NULL ,
`description` VARCHAR(45) NOT NULL ,
`tc_EventTags_ID` INT NULL ,
`tc_Orgs_ID` INT NOT NULL ,
`tc_PersonEvent_ID` INT NOT NULL ,
PRIMARY KEY (`ID`) ,
INDEX `fk_tc_Event_tc_EventTags1` (`tc_EventTags_ID` ASC) ,
INDEX `fk_tc_Event_tc_Orgs1` (`tc_Orgs_ID` ASC) ,
INDEX `fk_tc_Event_tc_PersonEvent1` (`tc_PersonEvent_ID` ASC) ,
CONSTRAINT `fk_tc_Event_tc_EventTags1`
FOREIGN KEY (`tc_EventTags_ID` )
REFERENCES `mcontest`.`tc_EventTags` (`ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_tc_Event_tc_Orgs1`
FOREIGN KEY (`tc_Orgs_ID` )
REFERENCES `mcontest`.`tc_Orgs` (`ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_tc_Event_tc_PersonEvent1`
FOREIGN KEY (`tc_PersonEvent_ID` )
REFERENCES `mcontest`.`tc_PersonEvent` (`ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = MyISAM;
USE `mcontest`;
DELIMITER $$
USE `mcontest`$$
CREATE TRIGGER eventTag_Trigger
AFTER insert ON tc_Event
FOR EACH ROW BEGIN
INSERT INTO tc_EventTags values('',NEW.tc_Event_ID);
END;
END$$
DELIMITER ;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
Why have put a tc_EventTags_ID in table tc_Event? What is the logic behind that?
I mean that the relationship between the 2 tables would be (I guess): 1 Event - many EventTags. This is already achieved by the tc_EventTags.tc_Event_ID which is a Foreign Key to tc_Event.
To answer your question:
As it is now, the Trigger tries for every row inserted in table Event, to add a row in table EventTag. But it will fail for 2 reasons:
EventTag has 2 Constraints (Foreign keys) which have to be fulfilled for the triggered insert to succeed. So, tc_Event_ID is ok but tc_Tag_ID has to be NOT NULL and reference the Tag table but the value you supply, '', probably is not in table Tag.
EDIT: the value you supply, '', is also a CHAR while it should be INT.
But trigger will probably not be started at all, since every time you insert a row in table Event, those constraints have to be fulfilled and one of them is the tc_EventTags_ID which references EventTag table. But EventTag table is empty. Do you see the circular logic here?

MySQL Workbench rename constraint

I use MySQL Workbench to design my database and then to export the SQL CREATE script. But when I run this script to create the database, I get an error - errno: 121.
It turns out that MySQL Workbench gives two constraints the same name, because both constraints use the same key (I have a table with primary key 'roleID' and I reference this key in two other tables).
Is there any way how I can rename the constraint directly in the designer, so when I forward engineer the SQL CREATE script, it will give no errors?
I tried double click the relation in the designer and give it a new caption, but it still generates the script with the original name.
Part of the generated script which creates the error:
CREATE TABLE IF NOT EXISTS users.roles (
roleID INT NOT NULL AUTO_INCREMENT ,
...
PRIMARY KEY (roleID) ,
...);
CREATE TABLE IF NOT EXISTS users.userRoles (
...
roleID INT NOT NULL ,
...
CONSTRAINT roleID
FOREIGN KEY (roleID )
REFERENCES users.roles (roleID ));
CREATE TABLE IF NOT EXISTS users.resourcePrivileges (
roleID INT NOT NULL ,
...
CONSTRAINT roleID
FOREIGN KEY (roleID )
REFERENCES users.roles (roleID ));
Not sure how you ended up with that. I took MySQL WorkBench for a spin, created two tables with a FK and it created
-- -----------------------------------------------------
-- Table `mydb`.`users`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`users` (
`idusers` INT NULL ,
PRIMARY KEY (`idusers`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`usersRoles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`usersRoles` (
`users_idusers` INT NOT NULL ,
PRIMARY KEY (`users_idusers`) ,
CONSTRAINT `fk_usersRoles_users`
FOREIGN KEY (`users_idusers` )
REFERENCES `mydb`.`users` (`idusers` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
Notice that the constraint has a unique name 'fk_usersRoles_users' that would not get duplicated since it uses table names.
Just for fun I added another relationship between the same tables and by default I get
-- -----------------------------------------------------
-- Table `mydb`.`usersRoles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`usersRoles` (
`users_idusers` INT NOT NULL ,
`users_idusers1` INT NOT NULL ,
PRIMARY KEY (`users_idusers`, `users_idusers1`) ,
INDEX `fk_usersRoles_users1` (`users_idusers1` ASC) ,
CONSTRAINT `fk_usersRoles_users`
FOREIGN KEY (`users_idusers` )
REFERENCES `mydb`.`users` (`idusers` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_usersRoles_users1`
FOREIGN KEY (`users_idusers1` )
REFERENCES `mydb`.`users` (`idusers` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
Which again is a non problem (all of the above is auto generated - I have only set the table names, primary key on referenced table and added two 1:N relationships)
NOTES: Version 5.2.30.
EDIT
Maybe something happened with your preferences. The default name for the fk constraints is defined on the model tab.
Error 121 is due to constraint name duplication.
Generally when generating your SQL script with MYSQL forward engineering export option, to resolve the issue we need to just ensure that the "Foreign Key Names" are unique in SQL script/ schema.
When you set a constraints for Foreign keys, will not assign different name that referring same primary key of some table. So, what am trying to say is that check all your index names in all the generated scripts if there any duplication. Rename to some other. Then you can proceed...