Cannot add foreign key constraint when value is NULL? - mysql

I using CodeIgniter for develop my application, I have insert a constraint for this table:
Appointments
CREATE TABLE IF NOT EXISTS `appointments` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`GroupID` int(11) NOT NULL,
`book_datetime` datetime DEFAULT NULL,
`start_datetime` datetime DEFAULT NULL,
`end_datetime` datetime DEFAULT NULL,
`notes` text,
`hash` text,
`is_unavailable` tinyint(4) DEFAULT '0',
`guid_users_provider` char(36) DEFAULT NULL,
`guid_users_customer` char(36) DEFAULT NULL,
`guid_services` char(36) DEFAULT NULL,
`id_google_calendar` text,
`resources_guid` char(36) DEFAULT NULL,
`data` int(11) NOT NULL,
`lastUpdated` varchar(36),
PRIMARY KEY (`id`),
KEY `guid_users_customer` (`guid_users_customer`),
KEY `guid_services` (`guid_services`),
KEY `guid_users_provider` (`guid_users_provider`),
KEY `resources_guid` (`resources_guid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Resources
CREATE TABLE IF NOT EXISTS `resources` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`GUID` char(36) NOT NULL UNIQUE,
`descrizione` varchar(255) NOT NULL,
`sigla` varchar(255) NOT NULL,
`planning` varchar(255) NOT NULL,
`hex_color` varchar(255) NOT NULL,
`data` int(11) NOT NULL,
`lastUpdated` varchar(36),
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
This is the constraint:
ALTER TABLE `appointments`
ADD CONSTRAINT `appointments_ibfk_5` FOREIGN KEY (`resources_guid`) REFERENCES `resources` (`GUID`) ON DELETE CASCADE ON UPDATE CASCADE;
The schema is builded correctly, but the problem is when I try to insert a record through my application, in particular the field resource_guid sometimes is NULL. Now, if I insert a record in PhpMyAdmin for test, in the appointments table and set the resource_guid as empty the record is added succesfully, but when I insert the record from my application on CodeIgniter I get this error:
Cannot add or update a child row: a foreign key constraint fails (scheduler.appointments, CONSTRAINT appointments_ibfk_5 FOREIGN KEY (resources_guid) REFERENCES resources (GUID) ON DELETE CASCADE ON UPDATE CASCADE)\",\"previous\":null,\
Now this is the content array of the query:
array(12) {
["guid_users_provider"]=>
string(36) "EE36D621-5E29-4674-81CB-B98622153E0C"
["start_datetime"]=>
string(19) "2015-12-30 23:19:00"
["end_datetime"]=>
string(19) "2015-12-31 00:45:00"
["notes"]=>
string(0) ""
["resources_guid"]=>
string(4) "null"
["is_unavailable"]=>
bool(false)
["guid_users_customer"]=>
string(36) "CDB8C010-7E51-4478-A341-F077E0460C88"
["guid_services"]=>
string(36) "31C40686-D72C-4361-B211-DCB2223552A9"
["book_datetime"]=>
string(19) "2015-12-31 01:12:39"
["hash"]=>
string(32) "5a9882faec12ab5bacb3445382176463"
["lastUpdated"]=>
string(27) "31-12-2015 10:12:39.5659760"
["GroupID"]=>
int(1)
}
How you can see the field resource_guid is NULL. Now the thing that I don't understand is (If I insert this in PhpMyAdmin as resource_guid set to NUll, so empty field, no error will be displayed, also from my application the error above appear).
This array is passed to the insert method of CodeIgniter like this:
if(!$this->db->insert('appointments', $appointment))
{
throw new Exception("Can't add record=> " . $this->db->_error_message());
}
How I can insert the resource also when is NULL? I mean, in my db table structure there is no renstriction for null value, infact in the appointments table is set with DEFAULT NULL. Someone could help me?

In your Appointments Table, you have given default value as NULL
Instead, give empty value as DEFAULT.
resources_guid` char(36) NOT NULL DEFAULT ''
To make an Existing Column as NOT NULL use MODIFY
ALTER TABLE Appointments MODIFY resources_guid char(36) NOT NULL DEFAULT ''

Look at your input resources_guid
["resources_guid"]=> string(4) "null"
It's a string with value "null", not a boolean NULL.
Pls check how you created that input. Make sure that is returning an actual NULL value. If you don't have control on that, you may need to change it manually by this way: (assuming the array as $appointment)
if($appointment["resources_guid"] == "null") {
$appointment["resources_guid"] = NULL;
}
Regarding the FOREIGN KEY, it should work as you have set it. There should be no problem for NULL values in the child field (unless the field is set as NOT NULL).

Related

Foreign key constraint fails but referenced row exists

I'm running MySQL 5.7.21 on Amazon RDS.
I know this question has been asked a thousand times, but I'm getting the issue on a scenario I wouldn't expect, so please read through before downvoting or marking as duplicate.
I'm not restoring the database, just running single INSERT queries, so is not a matter of ordering.
The referenced row does exist on the table; me and my colleagues had it triple checked.
As one might expect, disabling the FK checks with SET foreign_key_checks = 0 does make the query work.
I've seen this happening because of different table charsets, but in this case, both use utf8mb4. Also both have collation set to utf8mb4_general_ci.
This is happening in a production environment, so dropping the tables and recreating them is something I would like to avoid.
Some additional information:
The FK constraint was created AFTER the original tables were already populated.
Here is the relevant portion of the current DDL:
CREATE TABLE `VehicleTickets` (
`id` varchar(50) NOT NULL,
`vehiclePlate` char(7) NOT NULL,
`organizationId` varchar(50) NOT NULL,
`createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updatedAt` timestamp NULL DEFAULT NULL,
`status` varchar(15) NOT NULL DEFAULT 'OPEN',
`description` text NULL DEFAULT NULL,
`ticketInfo` json DEFAULT NULL,
`externalId` varchar(100) GENERATED ALWAYS AS (json_unquote(json_extract(`ticketInfo`,'$.externalId'))) VIRTUAL,
`value` decimal(10,2) GENERATED ALWAYS AS (json_unquote(json_extract(`ticketInfo`,'$.value'))) VIRTUAL,
`issuedAt` timestamp GENERATED ALWAYS AS (json_unquote(json_extract(`ticketInfo`,'$.issuedAt'))) VIRTUAL NOT NULL,
`expiresAt` timestamp GENERATED ALWAYS AS (json_unquote(json_extract(`ticketInfo`,'$.expiresAt'))) VIRTUAL NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `VehicleTickets_externalId_unq_idx` (`externalId`,`organizationId`),
KEY `VehicleTickets_vehiclePlate_idx` (`vehiclePlate`),
KEY `VehicleTickets_organizationId_idx` (`organizationId`),
KEY `VehicleTickets_issuedAt_idx` (`createdAt`),
KEY `VehicleTickets_expiresAt_idx` (`expiresAt`),
CONSTRAINT `VehicleTickets_Organizations_fk`
FOREIGN KEY (`organizationId`) REFERENCES `Organizations` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `Organizations` (
`id` varchar(50) NOT NULL,
`name` varchar(100) NOT NULL,
`taxPayerId` varchar(50) DEFAULT NULL,
`businessName` varchar(100) DEFAULT NULL,
`status` varchar(15) NOT NULL DEFAULT 'TESTING',
`createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updatedAt` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`activatedAt` timestamp NULL DEFAULT NULL,
`assetConfiguration` json DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
When I run:
select * from VehicleTickets where organizationId not in (
select id from Organizations
);
I get an empty result set.
However, if I run a query like this:
insert into `VehicleTickets` (
`id`,
`createdAt`,
`organizationId`,
`ticketInfo`,
`vehiclePlate`
)
values (
'... application generated id',
'... current date ',
'cjlchoksi01r8nfks3f51kht8', -- DOES EXIST on Organizations
'{ ... some JSON payload }',
'... vehicle plate'
)
This produces the following error:
Cannot add or update a child row: a foreign key constraint fails
(VehicleTickets, CONSTRAINT VehicleTickets_Organizations_fk
FOREIGN KEY (organizationId) REFERENCES Organizations (id))
Additionally, it gives me:
"errno": 1452,
"sqlState": "23000",
I've read through several threads regarding this issue, but couldn't find a similar case.

Mysql Percona crushes the table while trying to create a unique index on fields where there is a generated one

CREATE TABLE tasks (
`user_id` INT(10) UNSIGNED NOT NULL,
`name` VARCHAR(255) NOT NULL,
`code` VARCHAR(255) NOT NULL,
`params` JSON,
`hash` VARCHAR(32) GENERATED ALWAYS AS (MD5(`params`)),
`created_at` TIMESTAMP NULL DEFAULT NULL,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
CONSTRAINT `tasks_user_id_users_id_fk`
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
then i try to add a unique index on user_id and hash, i tried to do it during the table create, but there were a problem with the foreign key, so i decided to do it separately.
ALTER TABLE tasks
ADD UNIQUE INDEX `tasks_user_id_hash_unique_idx` (`user_id`, `hash`);
Then i get strange problem error 1146
Table '<dbname>.tasks' doesn't exist
Since then strange errors
1. I cannot delete it while it exists and i cannot do with it anything, cause it does not exist. After mysql reload I get the table deleted but if i try to create it again:
Error Code: 1813
Tablespace '<dbname>.tasks' exists.
I found the decision for unique field, i simply genereate md5( hash + user_id) UNIQUE. But How can I get rid of that problem which still exists and what is going on. It looks like a BUG in mysql Percona 5.7.14-7
so the right way to create the table
CREATE TABLE tasks (
`user_id` INT(10) UNSIGNED NOT NULL,
`name` VARCHAR(255) NOT NULL,
`code` VARCHAR(255) NOT NULL,
`params` JSON,
`hash` VARCHAR(32) GENERATED ALWAYS AS (MD5(CONCAT(`params`,`user_id`))) UNIQUE,
`created_at` TIMESTAMP NULL DEFAULT NULL,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
CONSTRAINT `tasks_user_id_users_id_fk`
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
But, again, the question with the ghosts still exists after the first tries!

Creating composite primarykey using a foreignkey and a non key attribute

This is my auto generated code after creating the batch table. while inserting data to this table
BatchID=1,Course_CourseID=1
BatchID=1,Course_CourseID=2
it is creating an error saying "Duplicate entry '1' for key 'BatchID_UNIQUE'".
I'm using C# 2010 express windows application as well as MySQl 5.1
My table schema is here
CREATE TABLE `batch` (
`BatchID` int(11) NOT NULL,
`Course_CourseID` int(11) NOT NULL,
`NoOfStudents` int(11) DEFAULT NULL,
`ClassRoom` varchar(45) DEFAULT NULL,
`StartDate` varchar(45) DEFAULT NULL,
`Day` varchar(45) DEFAULT NULL,
`Time` varchar(45) DEFAULT NULL,
PRIMARY KEY (`BatchID`,`Course_CourseID`),
UNIQUE KEY `BatchID_UNIQUE` (`BatchID`),
KEY `fk_Batch_Course1` (`Course_CourseID`),
CONSTRAINT `fk_Batch_Course1` FOREIGN KEY (`Course_CourseID`)
REFERENCES `course` (`CourseID`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Well, the error message quite clearly refers to this string:
UNIQUE KEY `BatchID_UNIQUE` (`BatchID`)
So what you have to do is either drop this index (with...
ALTER TABLE `batch` DROP INDEX `BatchID_UNIQUE`
... command, or just exclude this line from the table's definition (in CREATE TABLE).
All that said assuming that you really don't need your batch ids to be unique (in other words, there's no logical error in your INSERT statement. That seems to be the case, though: pair BatchID-Course_CourseID is already defined as unique (via PRIMARY KEY).
Try it this way. Drop your batch table and then run this sql. Rightly answered that you can not have two same vaues for a unique key. So I removed the unique key line as well.
CREATE TABLE IF NOT EXISTS `batch` (
`BatchID` int(11) NOT NULL,
`Course_CourseID` int(11) NOT NULL,
`NoOfStudents` int(11) DEFAULT NULL,
`ClassRoom` varchar(45) DEFAULT NULL,
`StartDate` varchar(45) DEFAULT NULL,
`Day` varchar(45) DEFAULT NULL,
`Time` varchar(45) DEFAULT NULL,
PRIMARY KEY (`BatchID`,`Course_CourseID`),
KEY `Course_CourseID` (`Course_CourseID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `batch` ADD CONSTRAINT `batch_ibfk_2` FOREIGN KEY (`Course_CourseID`)
REFERENCES `course` (`CourseId`) ON DELETE NO ACTION ON UPDATE NO ACTION;

on duplicate key update fails with error "Cannot add or update a child row"

I have a table with a compound primary key "name" and "id". The fields are actually "name","id","phone","amount","units","alias". I have the query
insert into MyTable (name,id,phone,amount) select "henry" as name, id,phone,amount from anotherTable
on duplicate key update phone=values(phone),amount=values(amount).
MySQL spits the following error:
Cannot add or update a child row: a foreign key constraint fails.
BTW, "id" is a foreign key.
Any help?
as requested below, the schema for other table is
CREATE TABLE `otherTable` (
`otherId` int(11) NOT NULL AUTO_INCREMENT,
`DOBId` int(11) NOT NULL,
`bankAccount` int(11) DEFAULT NULL,
`partialAmount` int(11) NOT NULL DEFAULT '0',
`id` int(11) NOT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`notes` varchar(299) DEFAULT NULL,
`latitude` decimal(8,5) DEFAULT NULL,
`longitude` decimal(8,5) DEFAULT NULL,
PRIMARY KEY (`otherId `),
KEY `DOBId ` (`DOBId `),
KEY `bankAccount ` (`bankAccount `),
KEY `id ` (`id `)
) ENGINE=InnoDB AUTO_INCREMENT=3305 DEFAULT CHARSET=utf8;
for myTable
CREATE TABLE `myTable` (
`name` int(11) NOT NULL,
`id` int(11) NOT NULL,
`appleNumber` int(11) DEFAULT NULL,
`amount` int(11) DEFAULT NULL,
`windowsNumber` int(11) DEFAULT NULL,
`phone` int(11) DEFAULT NULL,
`pens` int(11) DEFAULT NULL,
`pencils` int(11) DEFAULT NULL,
PRIMARY KEY (`name`,`id`),
KEY `id` (`id`),
CONSTRAINT `myTable_ibfk_1` FOREIGN KEY (`id`) REFERENCES `yet_another` (`id`)
The problem appears to be that the FK constraint you have on myTable is referencing the ids of yet_another, so when you are inserting ids from anotherTable you are breaking this FK constraint. Chances are there are ids in anotherTable that do not exist in yet_another table.
Understand this is a shot in the dark, based on the abstracted schema you posted. If you want a more solid answer, I'd have to see the actual schema.
The on duplicate key applies to the primary key. I take it you're using innodb. This is failing on a foreign key constraint. Which values of you table MyTable are foreign keys? Please post the create statement for the table that shows all keys and constraints for more detailed help.
Just a guess, but for grins I'm betting it's a column that's not in the insert that is a foreign key not allowing a null value.

MySQL: Error Message Can't create table (errno: 150)

I have two tables, 'po' and 'receive'
CREATE TABLE `po` (
`PO_ID` bigint(20) NOT NULL,
`SERVICE_TYPE` bit(1) DEFAULT NULL,
`ENTRY_DATE` date NOT NULL,
`RECEIPT_DATE` date DEFAULT NULL,
`TURNOVER` date DEFAULT NULL,
`MOBILIZATION` date DEFAULT NULL,
`SITE_NAME` varchar(255) NOT NULL,
`SITE_CODE` varchar(45) DEFAULT NULL,
`SITE_TIN` varchar(45) DEFAULT NULL,
`SITE_ADDRESS` varchar(255) NOT NULL,
`COST` decimal(11,2) NOT NULL,
`XML` text,
PRIMARY KEY (`PO_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
CREATE TABLE `receive` (
`RECEIPT_ID` varchar(100) NOT NULL,
`RECEIPT_DATE` date NOT NULL,
`PO_NUMBER` bigint(20) NOT NULL,
`SUPPLIER_ID` int(11) NOT NULL,
PRIMARY KEY (`RECEIPT_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
I'm trying to connect two tables by defining a foreign key 'fk_po' on the table 'receive'
ALTER TABLE `fourthwave`.`receive`
ADD CONSTRAINT `fk_po`
FOREIGN KEY (`PO_NUMBER` )
REFERENCES `fourthwave`.`po` (`PO_ID` )
ON DELETE SET NULL
ON UPDATE SET NULL
, ADD INDEX `fk_po` (`PO_NUMBER` ASC)
However, the alter query above throws an error :
Error Code: 1005. Can't create table 'fourthwave.#sql-aec_11' (errno:150)
Am i getting this error because the field's names, 'PO_ID' and 'PO_NUMBER' on both tables are different?
Execute SHOW ENGINE INNODB STATUS statement after ALTER TABLE, and you will see the error message - 'You have defined a SET NULL condition though some of the
columns are defined as NOT NULL'.
ALTER TABLE `receive`
ADD CONSTRAINT `fk_po`
FOREIGN KEY (`PO_NUMBER` )
REFERENCES `po` (`PO_ID` )
ON DELETE SET NULL
ON UPDATE SET NULL
, ADD INDEX `fk_po` (`PO_NUMBER` ASC);
SHOW ENGINE INNODB STATUS;
You need an index on PO_NUMBER in the receive table. The field you are referencing in a foreign key always should be indexed.