Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self referencing foreign key - mysql not set to null

Tags:

mysql

Indexes :

Keyname    Type   Unique  Packed  Column     Cardinality Collation  Null        
parent_id  BTREE  No      No      parent_id  1           A          YES 

Table : (comments)

Column      Type        Null    Default Extra
id          int(11)     No      None    AUTO_INCREMENT      
parent_id   int(11)     Yes     NULL

Relation view:

Column     Foreign key constraint (INNODB)
parent_id  'test_site'.'comments'.'id'  ON DELETE CASCADE   ON UPDATE  NO ACTION

Is it possible to have parent_id not set to NULL. I have tried setting the default value to '0' and inserting the value '0' but I get the following error.

Error:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update 
a child row: a foreign key constraint fails (`test_site`.`comments`, 
CONSTRAINT `comments_ibfk_2` FOREIGN KEY (`parent_id`) REFERENCES `comments` 
(`id`) ON DELETE CASCADE ON UPDATE NO ACTION)

Any help on this would be much appreciated, Thank you.

like image 834
Aaron Avatar asked Sep 26 '12 10:09

Aaron


People also ask

Do you need to specify NOT null for foreign key?

It is not required. A foreign key attribute without NOT NULL can contain NULL values, and this can be used to indicate that no such tuple in the referenced relation is applicable.

Can foreign key be not null in mySQL?

the foreign key, cannot be null by default in mySQL, the reason is simple, if you reference something and you let it null, you will loose data integrity. when you create the table set allow null to NOT and then apply the foreign key constraint.

Can a foreign key reference itself?

what is Self Referencing Foreign Key? Sometimes Foreign Key of a table references back to the primary key of the same table. In that case, the Foreign Key is said to be self-referencing. In this table, the 'employee_id' column is the primary key and the 'manager_id' is the foreign key.


1 Answers

Yes, it is possible, although you have to circumvent the foreign key constraint just once to insert a dummy record for the default value. Here's my workflow:

Here's the table creation:

root@localhost:playground > create table comments(id int auto_increment primary key, parent_id int not null default 0, constraint fk_parent_id foreign key (parent_id) references comments(id) on delete cascade on update cascade)engine=innodb;
Query OK, 0 rows affected (0.01 sec)

root@localhost:playground > show create table comments\G
*************************** 1. row ***************************
       Table: comments
Create Table: CREATE TABLE `comments` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `fk_parent_id` (`parent_id`),
  CONSTRAINT `fk_parent_id` FOREIGN KEY (`parent_id`) REFERENCES `comments` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

Now circumvent foreign key and insert dummy record.

root@localhost:playground > set session foreign_key_checks=0;
Query OK, 0 rows affected (0.00 sec)

root@localhost:playground > insert into comments (id) values (null);                                                                                              Query OK, 1 row affected (0.00 sec)

root@localhost:playground > set session foreign_key_checks=1;
Query OK, 0 rows affected (0.00 sec)

root@localhost:playground > select * from comments;
+----+-----------+
| id | parent_id |
+----+-----------+
|  1 |         0 |
+----+-----------+
1 row in set (0.00 sec)

root@localhost:playground > update comments set id = 0 where id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

root@localhost:playground > select * from comments;
+----+-----------+
| id | parent_id |
+----+-----------+
|  0 |         0 |
+----+-----------+
1 row in set (0.00 sec)

To make things neat and tidy I reset auto_increment (this is not necessary):

root@localhost:playground > alter table comments auto_increment=0;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

And from now on your foreign key constraint is working properly and your column is no longer nullable and has a default value:

root@localhost:playground > insert into comments (id) values (null);
Query OK, 1 row affected (0.00 sec)

root@localhost:playground > select * from comments;
+----+-----------+
| id | parent_id |
+----+-----------+
|  0 |         0 |
|  1 |         0 |
+----+-----------+
2 rows in set (0.00 sec)
like image 180
fancyPants Avatar answered Oct 05 '22 11:10

fancyPants