I am trying to insert values into my comments table and I am getting a error. Its saying that I can not add or update child row and I have no idea what that means.
my schema looks something like this
-- ----------------------------
-- Table structure for `comments`
-- ----------------------------
DROP TABLE IF EXISTS `comments`;
CREATE TABLE `comments` (
`id` varchar(36) NOT NULL,
`project_id` varchar(36) NOT NULL,
`user_id` varchar(36) NOT NULL,
`task_id` varchar(36) NOT NULL,
`data_type_id` varchar(36) NOT NULL,
`data_path` varchar(255) DEFAULT NULL,
`message` longtext,
`created` datetime DEFAULT NULL,
`modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_comments_users` (`user_id`),
KEY `fk_comments_projects1` (`project_id`),
KEY `fk_comments_data_types1` (`data_type_id`),
CONSTRAINT `fk_comments_data_types1` FOREIGN KEY (`data_type_id`) REFERENCES `data_types` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_comments_projects1` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_comments_users` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf32;
-- ----------------------------
-- Records of comments
-- ----------------------------
-- ----------------------------
-- Table structure for `projects`
-- ----------------------------
DROP TABLE IF EXISTS `projects`;
CREATE TABLE `projects` (
`id` varchar(36) NOT NULL,
`user_id` varchar(36) NOT NULL,
`title` varchar(45) DEFAULT NULL,
`description` longtext,
`created` datetime DEFAULT NULL,
`modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_projects_users1` (`user_id`),
CONSTRAINT `fk_projects_users1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf32;
-- ----------------------------
-- Records of projects
-- ----------------------------
INSERT INTO `projects` VALUES ('50dcbc72-3410-4596-8b71-0e80ae7aaee3', '50dcbc5c-d684-40bf-9715-0becae7aaee3', 'Brand New Project', 'This is a brand new project', '2012-12-27 15:24:02', '2012-12-27 15:24:02');
and the mysql statement I am trying to do looks something like this
INSERT INTO `anthonyl_fbpj`.`comments` (`project_id`, `user_id`, `task_id`, `data_type_id`, `message`, `modified`, `created`, `id`)
VALUES ('50dc845a-83e4-4db3-8705-5432ae7aaee3', '50dcbc5c-d684-40bf-9715-0becae7aaee3', '1', '50d32e5c-abdc-491a-a0ef-25d84e9f49a8', 'this is a test', '2012-12-27 19:20:46', '2012-12-27 19:20:46', '50dcf3ee-8bf4-4685-aa45-4eb4ae7aaee3')
the error I get looks like this
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a child row: a foreign key constraint fails
(anthonyl_fbpj.comments, CONSTRAINT fk_comments_projects1
FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE NO
ACTION ON UPDATE NO ACTION)
It just simply means that the value for column project_id on table comments you are inserting doesn't exist on table projects. Bear in mind that the values of column project_id on table comments is dependent on the values of ID on table Projects.
The value 50dc845a-83e4-4db3-8705-5432ae7aaee3 you are inserting for column project_id does not exist on table projects.
Make sure you have project_id in the fillable property of your Comment model.
I had the same issue, And this was the reason.
If you are adding new foreign key to an existing table and the columns are not null and not assigned default value, you will get this error,
Either you need to make it nullable or assign default value, or delete all the existing records to solve it.
Also make sure that the foreign key you add is the same type of the original column, if the column you're reference is not the same type it will fail too.
I hope my decision will help. I had a similar error in Laravel. I added a foreign key to the wrong table.
Wrong code:
Schema::create('comments', function (Blueprint $table) {
$table->unsignedBigInteger('post_id')->index()->nullable();
...
$table->foreign('post_id')->references('id')->on('comments')->onDelete('cascade');
});
Schema::create('posts', function (Blueprint $table) {
$table->bigIncrements('id');
...
});
Please note to the function on('comments') above. Correct code
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
that means that the value for column project_id on table comments you are inserting not only doesn't exist on table projects BUT also project_id probably doesn't have default value. E.g. in my case I set it as NULL.
As for Laravel you can consider this expressions as a chunk of code of a migration php file, for example:
class ForeinToPhotosFromUsers extends Migration
{ /** * Run the migrations. * * #return void */
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->unsignedBigInteger('photo_id')->nullable();// ! ! ! THIS STRING ! ! !
$table->foreign('photo_id')->references('id')->on('photos');
});
}
}
Obviously you had to create the Model class(in my case it was Photo) next to all these.
First delete the constraint "fk_comments_projects1" and also its index. After that recreate it.
You also get this error if you do not create and populate your tables in the right order. For example, according to your schema, Comments table needs user_id, project_id, task_id and data_type_id. This means that Users table, Projects table, Task table and Data_Type table must already have exited and have values in them before you can reference their ids or any other column.
In Laravel this would mean calling your database seeders in the right order:
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* #return void
*/
public function run()
{
$this->call(UserSeeder::class);
$this->call(ProjectSeeder::class);
$this->call(TaskSeeder::class);
$this->call(DataTypeSeeder::class);
$this->call(CommentSeeder::class);
}
}
This was how I solved a similar issue.
Maybe you have some rows in the table that you want to create de FK.
Run the migration with foreign_key_checks OFF
Insert only those records that have corresponding id field in contents table.
Issue could be because of no project record found in database with project_id you are trying to add...
In case someone is using Laravel and is getting this problem. I was getting this as well and the issue was in the order in which I was inserting the ids (i.e., the foreign keys) in the pivot table.
To be concrete, find below an example for a many to many relationship:
wordtokens <-> wordtoken_wordchunk <-> wordchunks
// wordtoken_wordchunk table
Schema::create('wordtoken_wordchunk', function(Blueprint $table) {
$table->integer('wordtoken_id')->unsigned();
$table->integer('wordchunk_id')->unsigned();
$table->foreign('wordtoken_id')->references('id')->on('word_tokens')->onDelete('cascade');
$table->foreign('wordchunk_id')->references('id')->on('wordchunks')->onDelete('cascade');
$table->primary(['wordtoken_id', 'wordchunk_id']);
});
// wordchunks table
Schema::create('wordchunks', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('text');
});
// wordtokens table
Schema::create('word_tokens', function (Blueprint $table) {
$table->increments('id');
$table->string('text');
});
Now my models look like follows:
class WordToken extends Model
{
public function wordchunks() {
return $this->belongsToMany('App\Wordchunk');
}
}
class Wordchunk extends Model
{
public function wordTokens() {
return $this->belongsToMany('App\WordToken', 'wordtoken_wordchunk', 'wordchunk_id', 'wordtoken_id');
}
}
I fixed the problem by exchanging the order of 'wordchunk_id' and 'wordtoken_id' in the Wordchunk model.
For code completion, this is how I persist the models:
private function persistChunks($chunks) {
foreach ($chunks as $chunk) {
$model = new Wordchunk();
$model->text = implode(' ', array_map(function($token) {return $token->text;}, $chunk));
$tokenIds = array_map(function($token) {return $token->id;}, $chunk);
$model->save();
$model->wordTokens()->attach($tokenIds);
}
}
I had this issue when I was accidentally using the WRONG "uuid" in my child record. When that happens the constraint looks from the child to the parent record to ensure that the link is correct. I was generating it manually, when I had already rigged my Model to do it automatically. So my fix was:
$parent = Parent:create($recData); // asssigning autogenerated uuid into $parent
Then when I called my child class to insert children, I passed this var value:
$parent->uuid
Hope that helps.
I had the same error, the problem was that I was trying to add role_id foreign to the users table, but role_id did not have a default value, so the DB did not allow me to insert the column because I already had some users and it didn't know how to add the column to them.
Since I was in development I just used migrate:fresh, but if I was on production, I would probably set a default value to the role_id and not make it not constrained until I had the corresponding role on the DB.
Could be you are inserting a foreign key value that does not match with that of the primary key.
In my case it didn't work because I was leaving a space in one of the names of in the model.
I had a table fulfilled with some entries that has dead foreigners keys.
once i cleaned the table, i was able to add a new constraint.
DELETE FROM `table_with_bad_entries` WHERE `expected_foreign_key` not in (select `id` from `the_referenced_table`);
I just exported the table deleted and then imported it again and it worked for me. This was because i deleted the parent table(users) and then recreated it and child table(likes) has the foreign key to parent table(users).
Related
I have created a database with this query:
CREATE TABLE progettoschemas.categories (
id DOUBLE NOT NULL,
name VARCHAR(255) NOT NULL,
fatherid DOUBLE NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (fatherid) REFERENCES progettoschemas.categories(id) ON UPDATE CASCADE ON DELETE CASCADE)
because I want a tree structure where an element is related to its father id. Now the problem is that I'd like the root to have parameters like: id=1 name=root fatherid=0 (the fatherid=0 is important and I prefer not to change it cause if I do I will have to modify a lot of my code) but obviously mysql doesn't allow me to do it because there is no reference with that 0 as fatherid. Is there a way to solve my problem mantaining the parameters I want or I have to modify them in some ways?
I didn't find any effective solution without modifying my db structure, so I was forced to change my db to:
CREATE TABLE progettoschemas.categories (
id DOUBLE NOT NULL,
name VARCHAR(255) NOT NULL,
fatherid DOUBLE,
PRIMARY KEY (id),
FOREIGN KEY (fatherid) REFERENCES progettoschemas.categories(id) ON UPDATE CASCADE ON DELETE CASCADE)
and added a row called root with id=0 and fatherid=null
I have a table called 'estoque' with a foreign key that references another table called 'produto'. Then I've populated both tables with a few rows.
Here are my tables:
CREATE TABLE `produto` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`NOME` varchar(45) NOT NULL,
`PRECO` float NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `NOME_UNIQUE` (`NOME`)
);
CREATE TABLE `estoque` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`ID_PRODUTO` int(11) NOT NULL,
`QUANTIDADE_PRODUTO` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `fk_Estoque_Produto1_idx` (`ID_PRODUTO`),
CONSTRAINT `fk_Estoque_Produto1` FOREIGN KEY (`ID_PRODUTO`)
REFERENCES `produto` (`ID`)
);
I need 'estoque' to always reference all existing rows on 'product'. So I'e created an AFTER INSERT and an AFTER UPDATE triggers on product:
CREATE TRIGGER `cadastrar_novo_produto_no_estoque`
AFTER INSERT ON `produto`
FOR EACH ROW
INSERT IGNORE INTO estoque (ID_PRODUTO)
VALUES (NEW.ID);
EDIT: Actually, since I can't alter the 'ID' column on 'produto' because it is a primary key, I've think I don't need the AFTER UPDATE trigger at all. Am I right?
CREATE TRIGGER `atualizar_novo_produto_no_estoque`
AFTER UPDATE ON `produto`
FOR EACH ROW
UPDATE estoque
SET estoque.ID_PRODUTO = NEW.ID
WHERE OLD.estoque.ID_PRODUTO = OLD.ID;
Now I need a trigger so that every time I delete a row from 'product', it also deletes the corresponding row in 'estoque'.
I've tried creating one like this:
CREATE TRIGGER `deletar_produto_inexistente_no_estoque`
BEFORE DELETE ON `produto`
FOR EACH ROW DELETE FROM estoque
WHERE estoque.ID_PRODUTO = ID;
But whenever I try to delete a row from 'produto' I get the following error:
ERROR 1175: 1175: You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column.
SQL Statement:
DELETE FROM `papelaria`.`produto` WHERE (`ID` = '6')
So I've tried it with the OLD keyword, as such:
CREATE TRIGGER `deletar_produto_inexistente_no_estoque`
BEFORE DELETE ON `produto`
FOR EACH ROW DELETE FROM estoque
WHERE OLD.estoque.ID_PRODUTO = OLD.ID;
And then I get this error instead:
ERROR 1054: 1054: Unknown column 'OLD.estoque.ID_PRODUTO' in 'where clause'
SQL Statement:
DELETE FROM `papelaria`.`produto` WHERE (`ID` = '6')
What am I missing or doing wrong?
P.S.: Not sure if it's worth mentioning but I'm fairly new to sql and programming in general, so I'd appreciate it if you took it into consideration when answering (for all purposes, just assume I don't know anything about anything ^^)
Thank you in advance!
You can modify your FK to:
CONSTRAINT `fk_Estoque_Produto1`
FOREIGN KEY (`ID_PRODUTO`)
REFERENCES `produto` (`ID`)
ON DELETE CASCADE
Then you will not need the before delete trigger any longer as records in estoque table will be deleted automatically.
Similar, adding ON UPDATE CASCADE will solve your 'update issue' in case someone update record's PK.
Still not sure why you'd like to have the dummy records in the estoque table.
In my local environment database(localhost:3306, mysql 5.7.20), everything works fine.
but In aws RDS database(mysql 5.7.22), Unhandled rejection SequelizeDatabaseError: Cannot add foreign key constraint error occur.
full log is below.
Executing (default):
CREATE TABLE IF NOT EXISTS `folders`
(`id` CHAR(36) BINARY , `folderName` VARCHAR(255),
`folderCoverImage` VARCHAR(255), `createdAt` DATETIME NOT NULL,
`updatedAt` DATETIME NOT NULL, `fk_user_id` CHAR(36) BINARY,
`fk_category_id` CHAR(36) BINARY,
PRIMARY KEY (`id`),
FOREIGN KEY (`fk_user_id`) REFERENCES `users` (`id`)
ON DELETE CASCADE ON UPDATE RESTRICT,
FOREIGN KEY (`fk_category_id`) REFERENCES `categories` (`id`)
ON DELETE SET NULL ON UPDATE CASCADE) ENGINE=InnoDB;
Unhandled rejection SequelizeDatabaseError: Cannot add foreign key constraint
users:
CREATE TABLE IF NOT EXISTS `users` (`id` CHAR(36) BINARY , `username` VARCHAR(255), `email` VARCHAR(255) UNIQUE, `socialProvider` VARCHAR(255), `profileImg` TEXT, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
categories:
CREATE TABLE IF NOT EXISTS `categories` (`id` CHAR(36) BINARY , `name` VARCHAR(255) UNIQUE, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Executing (default): SHOW INDEX FROM categories
and my node.js code here.
Folder.associate = function associate () {
Folder.belongsTo(User, {
foreignKey: 'fk_user_id',
onDelete: 'CASCADE',
onUpdate: 'restrict'
});
Folder.hasMany(Work, {
as: 'Work',
foreignKey: 'fk_folder_id',
onDelete: 'CASCADE',
onUpdate: 'restrict'
});
Folder.belongsTo(Category, {
as: 'Category',
foreignKey: 'fk_category_id'
});
};
also, table users, categories, post, tag have existed.
Create table order is here http://sqlfiddle.com/#!9/2162ca
I don't know why it dosn't work at aws RDS.
Can you check the order of create tables. When you change the order so that table (whose primary key is being referenced) already exists the error willnot occur.
Possible duplicate here
The problem might be the database is not empty. In such case, when one of the rows does not fulfill foreign key requirement, adding the requirement to the whole table will fail.
Make sure all the rows on the AWS RDS can fulfill the requirement and that their foreign records exist.
Example:
let's say you create a table with books and user_id column. You decide that user_id with a value of "0" means no user was assigned to the row (book is still in the library).
Then, the code changes and you implement user_id as a foreign key (user_id should now point to "user" table, "id" column
which you would normally do via:
ALTER TABLE database.books
ADD FOREIGN KEY book_user_id(user_id) REFERENCES user(id);
Now, if you already have books in your database with user_id column having "0" value, the query will fail, because there are records that point to non-existing user (with id of "0").
To fix this, you need to update the records with broken soon-to-be reference first.
In this particular case, creatng a "librarian" user with some id of i.e 123, then doing:
UPDATE books set user_id=123 WHERE user_id=0;
Would do the trick and allow you to create the foreign key without issue.
UPDATE: I have a ticket into my hosting provider (FatCow) as they are able to duplicate the issue. I will post any conclusions here.
I have a MySQL database like so:
table || pk
-----------
performers -> pID
genres -> gID
venues -> vID
I also have an events table that looks something like this:
eID (PK)
ePerformer (INDEX)
eGenre (INDEX)
eVenue (INDEX)
They are all the same type: INT(11). All of the tables are InnoDB. I want to setup the relationships in phpMyAdmin using the Relation View on the events table, but when I try to save:
ePerformer: performers->pID ON DELETE RESTRICT, ON UPDATE RESTRICT
eGenre: genres->gID ON DELETE RESTRICT, ON UPDATE RESTRICT
etc...
I get this error back for each field: No index defined!
I thought perhaps I was doing it backwards, so I tried setting each relationship from the other tables but I'm getting the same error.
What gives?
Using a similar structure I am able to create the relations. You've already checked several of the obvious things (primary key on the referenced keys, InnoDB, etc).
When I first created the events table, using the phpMyAdmin dropdown to select INDEX for each of the three fields you indicate, it created a composite index on all three fields, which didn't work; I had to remove that index and manually create an INDEX on each field individually.
The composite index:
The working individual indexes:
You could try the Designer feature (which requires you to set up the "phpMyAdmin configuration storage"); I find it superior to the Relation View when manipulating relations.
From the events table (I know, you already said you were on the proper table), click the Structure tab and next the Relation View link, you should be able to do this:
In this case I had already created the events_ibfk_1 relationship through Designer and fk_venue through Relation View; this screenshot was taken just prior to creating the fk_performer one so what you see here is exactly what I had in place before clicking "Save".
Not sure if that helps any, but I'm able to do it with what you've provided...so maybe if it still doesn't work you can export your complete existing table structure and I'll try to make that work.
For what it's worth, here's the export of the table structure I had working:
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
CREATE TABLE IF NOT EXISTS `events` (
`eID` int(11) NOT NULL,
`ePerformer` int(11) NOT NULL,
`eGenre` int(11) NOT NULL,
`eVenue` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `genres` (
`gID` int(11) NOT NULL,
`g` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `performers` (
`pID` int(11) NOT NULL,
`p` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `venues` (
`vID` int(11) NOT NULL,
`v` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `events`
ADD PRIMARY KEY (`eID`), ADD KEY `i_perf` (`ePerformer`), ADD KEY `i_genre` (`eGenre`), ADD KEY `i_venue` (`eVenue`);
ALTER TABLE `genres`
ADD PRIMARY KEY (`gID`);
ALTER TABLE `performers`
ADD PRIMARY KEY (`pID`);
ALTER TABLE `venues`
ADD PRIMARY KEY (`vID`);
ALTER TABLE `events`
ADD CONSTRAINT `fk_performer` FOREIGN KEY (`ePerformer`) REFERENCES `performers` (`pID`),
ADD CONSTRAINT `events_ibfk_1` FOREIGN KEY (`eGenre`) REFERENCES `genres` (`gID`),
ADD CONSTRAINT `fk_venue` FOREIGN KEY (`eVenue`) REFERENCES `venues` (`vID`);
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.