Mysql Set NULL value in Foreign key column [duplicate] - mysql

This question already has answers here:
how to pass a null value to a foreign key field?
(3 answers)
Closed 6 years ago.
I'm trying to set a NULL value in the deserved_slope_2 column when the user edits the value in a form. Unfortunately this column is a foreign key that links to a primary key (auto increment index) of a column of another table.
When running the request I get:
Error Number: 1452
Cannot add or update a child row: a foreign key constraint fails (`game_skisimulation`.`game_created_lifts`, CONSTRAINT `fk_game_created_lifts_game_created_slopes2` FOREIGN KEY (`deserved_slope_2`) REFERENCES `game_created_slopes` (`id_created_slopes`) ON DE)
UPDATE game_created_lifts SET deserved_slope_2 = '0' WHERE id_created_lifts = '200' LIMIT 1
I've read that this is because the NULL ID doesn't exist in the referred table. Unfortunately it seems that I cannot set NULL either in this column:
A primary key column cannot contain NULL values.
How can I solve this problem?
I want to set NULL in the deserved_slope_2 column (to reset it).
-- Table structure for table game_created_lifts
CREATE TABLE `game_created_lifts` (
`id_created_lifts` int(11) NOT NULL,
`id_player` int(11) NOT NULL,
`deserved_slope_1` int(11) DEFAULT NULL,
`deserved_slope_2` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- RELATIONS FOR TABLE `game_created_lifts`:
-- `deserved_slope_1`
-- `game_created_slopes` -> `id_created_slopes`
-- `deserved_slope_2`
-- `game_created_slopes` -> `id_created_slopes`
-- Table structure for table game_created_slopes
CREATE TABLE `game_created_slopes` (
`id_created_slopes` int(11) NOT NULL,
`id_player` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Setting a value to null in a column that has a foreign key constraint which depends on a unique and not null column in should be pretty straight-forward
UPDATE game_created_lifts SET deserved_slope_2 = NULL WHERE id_created_lifts = '200' LIMIT 1;
Go to SQL Fiddle to see it online.
Test data:
create table a (a int primary key);
create table b (a int references a(a));
insert into a(a) values (1);
insert into b(a) values (1);
update b set a = null;
Query:
select * from b
Result:
(null)

Related

Trying to add a constraint that makes the value on one column depending of another column's value in mysql

On MySQL I have a problem regarding a constraint I'm making on the column "loueur_id" of my vehicle table. I'm trying to make it so when the column location have "disponible" or "en_revision" as value then the value of "loueur_id" become null but if the value of "location" is NULL then "loueur_id" value become the id of the customer who is renting the vehicle
CREATE TABLE IF NOT EXISTS `vehicule` (
`id` int NOT NULL AUTO_INCREMENT,
`typ` int NOT NULL UNIQUE,
`nb` int NOT NULL,
`caract` json NOT NULL,
`location` varchar(20),
`photo` varchar(20) NOT NULL,
`loueur_id` int,
PRIMARY KEY (`id`),
INDEX per_loueur (`loueur_id`),
FOREIGN KEY(`loueur_id`) REFERENCES `client`(`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
ALTER TABLE `vehicule`
ADD CONSTRAINT CK_location CHECK ((`location` in('disponible', 'en_revision')))
ADD CONSTRAINT CK_loueur CHECK (`loueur_id` = CASE WHEN `location` in('disponible', 'en_revision' THEN NULL ELSE `loueur_id` END CASE));
This is what I tried to do but mysql said that I've made a syntax error on my last Check constraint. Can someone help me find the problem's solution please?
It is often simpler to express the constraints with boolean logic rather than with case expressions. I think this does what you want:
alter table `vehicule`
add constraint ck_location check ((location in('disponible', 'en_revision'))),
add constraint ck_loueur check (
(location in('disponible', 'en_revision') and loueur_id is null)
or (location is null and loueur_id is not null)
)
Note that check constraints are available starting MySQL 8.0.16 only. In earlier versions, they are parsed without errors, but not actually enforced.
You can do this with one constraint:
alter table `vehicule`
add constraint ck_vehicule_location_loueur_id
check ( (location in ('disponible', 'en_revision') and loueur_id is null) or
(location is null and loueur_id is not null)
);

How to use more than 1 auto-increment column in MySQL

I want to create a table name Users where I should have have columns User, cookieID, sessionID, Geo and then I want to first three columns to have some random unique value assigned automatically. I tried to make all three columns AUTO_INCREMENT with User column PRIMARY and 'cookieIDandsessionIDcolumnUNIQUE`. The SQL code is:
CREATE TABLE `users` ( `User` VARCHAR(20) NOT NULL AUTO_INCREMENT ,
`cookieID` INT(20) NULL DEFAULT NULL AUTO_INCREMENT ,
`sessionID` INT(20) NULL DEFAULT NULL AUTO_INCREMENT ,
`Geo` VARCHAR(30) NULL DEFAULT NULL ,
PRIMARY KEY (`User`), UNIQUE (`cookieID`), UNIQUE (`sessionID`), UNIQUE (`Geo`));
But, it did not work because only one column can be declared as AUTO_INCREMENT which must be PRIMARY.
What is the another approach to do this?
Since the auto-increment cannot be applied to multiple to rows and there no option for sequence in MySQL. You can use triggers for the unique update of the row with datetime.
Change to table creation to be of single auto-increment row.
CREATE TABLE `users` ( `User` VARCHAR(20) NOT NULL,
`cookieID` INT(20) NULL DEFAULT NULL,
`sessionID` INT(20) NULL DEFAULT NULL AUTO_INCREMENT ,
`Geo` VARCHAR(30) NULL DEFAULT NULL,
PRIMARY KEY (`User`), UNIQUE (`cookieID`), UNIQUE (`sessionID`), UNIQUE (`Geo`));
Create a trigger on the same table as below. You can set the unique values under the SET for as many column as you want.
CREATE DEFINER=`root`#`localhost` TRIGGER `users_BEFORE_INSERT` BEFORE INSERT ON `users` FOR EACH ROW BEGIN
SET
NEW.cookieID = (SELECT curdate()+curtime());
END
Now when you insert into the table as below.
insert into `users`(`User`) values("test");
You table looks like this.
User cookieID sessionID Geo
test 20315169 0 NULL
If the value which are auto incrementing, you wanna keep both values the same. Then copy the value of one column to another during insertion time of new value.

Mysql Auto Increment increasing by 2 and 1?

If I create a table with the following syntax,
CREATE TABLE IF NOT EXISTS `hashes` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`hash` binary(20) NOT NULL,
PRIMARY KEY (`id`,`hash`),
UNIQUE KEY (`hash`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE = 4 AUTO_INCREMENT=1
PARTITION BY KEY(`hash`)
PARTITIONS 10;
And insert queries with the following syntax
INSERT INTO hashes (hash) VALUES ($value) ON DUPLICATE KEY UPDATE hash = hash
Then the auto increment column works as expected both if the row is inserted or updated.
Although creating the table without the partition like below and inserting with the query above the auto increment value will increase by 1 on every update or insert causing the A_I column to be all over place as the query could do 10 updates and then 1 insert causing the column value to jump 10 places.
CREATE TABLE IF NOT EXISTS `hashes` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`hash` binary(20) NOT NULL,
PRIMARY KEY (`id`,`hash`),
UNIQUE KEY (`hash`)
) ENGINE=InnoDB AUTO_INCREMENT=1;
I understand why the value increases on an update with INNO_DB but I do not understand why it doesn't when the table is partitioned?
you cannot change that, but you can try something like this:
mysql> set #a:= (select max(id) + 2 from hashes);
mysql> insert into hashes (id) values ($value) on duplicate key update id=#a;
NOTE: the partitions change a little bit after mysql 5.6, which version do you have?

MySQL workbench - self referring table and custom script

I use MySQL 5.3.28 to create my database. One of the tables is referring itself, which is a big pain. Here is the originally created code:
CREATE TABLE IF NOT EXISTS `dhbpsychiatry`.`activity` (
`ActivityId` INT(11) NOT NULL AUTO_INCREMENT ,
`NeedsRepeating` BINARY(1) NULL DEFAULT NULL ,
`Prerequisition` INT(11) NOT NULL DEFAULT 0 ,
`ActivityName` VARCHAR(45) NOT NULL ,
`ActivityDescription` VARCHAR(45) NULL ,
PRIMARY KEY (`ActivityId`) ,
INDEX `Prerequisition` (`ActivityId` ASC) ,
CONSTRAINT `Prerequisition`
FOREIGN KEY (`ActivityId` )
REFERENCES `dhbpsychiatry`.`activity` (`ActivityId` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
Problem is of course with creating first row.
INSERT INTO `dhbpsychiatry`.`activity` (`ActivityId`, `Prerequisition`,
`ActivityName`) VALUES (1, 1, 'No prerequisition');
returns
ERROR 1452: Cannot add or update a child row: a foreign key constraint fails
Same if I try even simpler
INSERT INTO `dhbpsychiatry`.`activity` (`ActivityName`)
VALUES ('No prerequisition');
I think I've tried all possibilities, making the FK nullable, not nullable, with or without default value...
After digging a bit I've found something that works:
SET FOREIGN_KEY_CHECKS = 0;
Insert into activity (ActivityID, ActivityName) VALUES (0,'No prerequisition');
SET FOREIGN_KEY_CHECKS = 1;
So I created a new SQL script in workbench with those lines.
So I have two questions here:
How I can add the first row without the script?
or if its impossible
2 How can I automatically add this script to be executed whenever I froward engineer the database?
Your indexes and Foreign key definitions are confused. Main issue is that column ActivityId is referencing itself.
Try this:
CREATE TABLE IF NOT EXISTS `dhbpsychiatry`.`activity` (
`ActivityId` INT(11) NOT NULL AUTO_INCREMENT ,
`NeedsRepeating` BINARY(1) NULL DEFAULT NULL ,
`Prerequisition` INT(11) NOT NULL DEFAULT 0 ,
`ActivityName` VARCHAR(45) NOT NULL ,
`ActivityDescription` VARCHAR(45) NULL ,
PRIMARY KEY (`ActivityId`) ,
INDEX `Prerequisition_idx` (`Prerequisition`) , --- changed the index name
--- and the indexed column
CONSTRAINT `Prerequisition_fk` --- changed the constraint name
FOREIGN KEY (`Prerequisition` ) --- main issue !! changed
--- the referencing column
REFERENCES `dhbpsychiatry`.`activity` (`ActivityId`)
ON DELETE NO ACTION
ON UPDATE NO ACTION
)

MySQL Duplicate primary key on unexisting key

I've got a weird problem on a MySQL table. When trying to insert a new row, it says the primary key is duplicate. My primary key is auto incremental and is not set within my query (automatically set by MySQL).
The problem is I get a "Duplicate primary key" error on a key that doesn't even exists (I checked). I solved the problem increasing the current auto_increment value but I can't understand how it happened.
Any help would be great.
Edit
Table creation
CREATE TABLE `articles_mvt` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`ext_article_id` int(5) NOT NULL,
`date_mvt` date NOT NULL,
`qte` float(4,2) NOT NULL,
`in_out` enum('in','out') NOT NULL,
`ext_nateco_id` int(5) NOT NULL,
`ext_agent_id` int(5) NOT NULL COMMENT 'Demandeur',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1647 ;
Problematic query
INSERT INTO articles_mvt (
`ext_article_id`,
`date_mvt`,
`qte`,
`in_out`,
`ext_nateco_id`,
`ext_agent_id`
)
VALUES (
'".$_POST["numArticle"]."',
'".dateSql($_POST["date_mvt"])."',
".$_POST["qte_entier"].".".$_POST["qte_virgule"].",
'".$_POST["in_out"]."',
".$_POST["numNateco"].",
".$_POST["demandeur"]."
)
FYI variables are sanitized earlier in the code ;)
Well i think at that time you did not check auto Inc flag on primary key. So when you try to enter than value 0 is insert in the primary key and for second entry it gives error. like that
ID Value
0 A ok it not give error
0 ff it gives error..
Or you may try to insert a row whose ID is already exist like
ID Value
11 A ok it not give error
11 ff it gives error..