Ошибка при подтверждении новой строки foreign key constraint failed

I’ve set up two tables:

CREATE TABLE A
(
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    name TEXT
 );

CREATE TABLE B
(
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    id2 INTEGER,
    book TEXT,
    FOREIGN KEY(id2) REFERENCES A(id)
);

After I insert data into A, it looks like this:

1    John

2    Amy

3    Peter

After I insert data into B, it looks like this:

1     1     Lord of the Rings

2     1     Catch 22

3     2     Sum of All Fears

4     3     Hunt for Red October

I then execute the following statement:

delete from a where id=1;

I get the following: "Error: foreign key constraint failed"

I then restart sqlite3 and try again but this time I enter this first:

PRAGMA foreign_keys = 1;

it still doesn’t work……

I’ve set up two tables:

CREATE TABLE A
(
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    name TEXT
 );

CREATE TABLE B
(
    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    id2 INTEGER,
    book TEXT,
    FOREIGN KEY(id2) REFERENCES A(id)
);

After I insert data into A, it looks like this:

1    John

2    Amy

3    Peter

After I insert data into B, it looks like this:

1     1     Lord of the Rings

2     1     Catch 22

3     2     Sum of All Fears

4     3     Hunt for Red October

I then execute the following statement:

delete from a where id=1;

I get the following: "Error: foreign key constraint failed"

I then restart sqlite3 and try again but this time I enter this first:

PRAGMA foreign_keys = 1;

it still doesn’t work……

The MySQL ERROR 1452 happens when you try to execute a data manipulation query into a table that has one or more failing foreign key constraints.

The cause of this error is the values you’re trying to put into the table are not available in the referencing (parent) table.

Let’s see an example of this error with two MySQL tables.

Suppose you have a Cities table that contains the following data:

+----+------------+
| id | city_name  |
+----+------------+
|  1 | York       |
|  2 | Manchester |
|  3 | London     |
|  4 | Edinburgh  |
+----+------------+

Then, you create a Friends table to keep a record of people you know who lives in different cities.

You reference the id column of the Cities table as the FOREIGN KEY of the city_id column in the Friends table as follows:

CREATE TABLE `Friends` (
  `firstName` varchar(255) NOT NULL,
  `city_id` int unsigned NOT NULL,
  PRIMARY KEY (`firstName`),
  CONSTRAINT `friends_ibfk_1` 
    FOREIGN KEY (`city_id`) REFERENCES `Cities` (`id`)
)

In the code above, a CONSTRAINT named friends_ibfk_1 is created for the city_id column, referencing the id column in the Cities table.

This CONSTRAINT means that only values recoded in the id column can be inserted into the city_id column.

(To avoid confusion, I have omitted the id column from the Friends table. In real life, You may have an id column in both tables, but a FOREIGN KEY constraint will always refer to a different table.)

When I try to insert 5 as the value of the city_id column, I will trigger the error as shown below:

INSERT INTO `Friends` (`firstName`, `city_id`) VALUES ('John', 5);

The response from MySQL:

ERROR 1452 (23000): Cannot add or update a child row: 
a foreign key constraint fails 
(`test_db`.`friends`, CONSTRAINT `friends_ibfk_1` 
FOREIGN KEY (`city_id`) REFERENCES `cities` (`id`))

As you can see, the error above even describes which constraint you are failing from the table.

Based on the Cities table data above, I can only insert numbers between 1 to 4 for the city_id column to make a valid INSERT statement.

INSERT INTO `Friends` (`firstName`, `city_id`) VALUES ('John', 1);

-- Query OK, 1 row affected (0.00 sec)

The same error will happen when I try to update the Friends row with a city_id value that’s not available.

Take a look at the following example:

UPDATE `Friends` SET city_id = 5 WHERE `firstName` = 'John';

-- ERROR 1452 (23000): Cannot add or update a child row

There are two ways you can fix the ERROR 1452 in your MySQL database server:

  • You add the value into the referenced table
  • You disable the FOREIGN_KEY_CHECKS in your server

The first option is to add the value you need to the referenced table.

In the example above, I need to add the id value of 5 to the Cities table:

INSERT INTO `Cities` VALUES (5, 'Liverpool');

-- Cities table:
+----+------------+
| id | city_name  |
+----+------------+
|  1 | York       |
|  2 | Manchester |
|  3 | London     |
|  4 | Edinburgh  |
|  5 | Liverpool  |
+----+------------+

Now I can insert a new row in the Friends table with the city_id value of 5:

INSERT INTO `Friends` (`firstName`, `city_id`) VALUES ('Susan', 5);

-- Query OK, 1 row affected (0.00 sec)

Disabling the foreign key check

The second way you can fix the ERROR 1452 issue is to disable the FOREIGN_KEY_CHECKS variable in your MySQL server.

You can check whether the variable is active or not by running the following query:

SHOW GLOBAL VARIABLES LIKE 'FOREIGN_KEY_CHECKS';

-- +--------------------+-------+
-- | Variable_name      | Value |
-- +--------------------+-------+
-- | foreign_key_checks | ON    |
-- +--------------------+-------+

This variable causes MySQL to check any foreign key constraint added to your table(s) before inserting or updating.

You can disable the variable for the current session only or globally:

-- set for the current session:
SET FOREIGN_KEY_CHECKS=0;

-- set globally:
SET GLOBAL FOREIGN_KEY_CHECKS=0;

Now you can INSERT or UPDATE rows in your table without triggering a foreign key constraint fails:

INSERT INTO `Friends` (`firstName`, `city_id`) VALUES ('Natalia', 8);
-- Query OK, 1 row affected (0.01 sec)

UPDATE `Friends` SET city_id = 17 WHERE `firstName` = 'John';
-- Query OK, 1 row affected (0.00 sec)
-- Rows matched: 1  Changed: 1  Warnings: 0

After you’re done with the manipulation query, you can set the FOREIGN_KEY_CHECKS active again by setting its value to 1:

-- set for the current session:
SET FOREIGN_KEY_CHECKS=1;

-- set globally:
SET GLOBAL FOREIGN_KEY_CHECKS=1;

But please be warned that turning off your FOREIGN_KEY_CHECKS variable will cause the city_id column to reference a NULL column in the cities table.

It may cause problems when you need to perform a JOIN query later.

Now you’ve learned the cause of ERROR 1452 and how to resolve this issue in your MySQL database server. Great work! 👍

Wondering how to resolve MySQL Error 1452? We can help you.

At Bobcares, we offer solutions for every query, big and small, as a part of our Microsoft SQL Server Support Services.

Let’s take a look at how our Support Team is ready to help customers with MySQL Error 1452.

How to resolve MySQL Error 1452?

Usually, this error occurs when we try to execute a data manipulation query into a table that has one or more failing foreign key constraints.

What causes MySQL Error 1452?

The cause of this error is the values we are trying to put into the table are not available in the referencing (parent) table.

When a column of a table is referenced from another table, it is called Foreign Key.

For example, consider a table City that contains the name of a city and its ID.

Also, there is another table Buddies to keep a record of people that we know who lives in different cities.

We have to reference the id column of the City table as the FOREIGN KEY of the city_id column in the friends table as follows:

CREATE TABLE friends (
firstName varchar(255) NOT NULL,
city_id int unsigned NOT NULL,
PRIMARY KEY (firstName),
CONSTRAINT friends_ibfk_1
FOREIGN KEY (city_id) REFERENCES City (id)
)

In the code above, a CONSTRAINT named buddies_ibfk_1 is created for the city_id column, referencing the id column in the City table.

This CONSTRAINT means that only values in the id column can be inserted into the city_id column.

If we try to insert a value that is not present in id column into the city_id column, it will trigger the error as shown below:

ERROR 1452 (23000): Cannot add or update a child row:
a foreign key constraint fails
(test_db.friends, CONSTRAINT friends_ibfk_1
FOREIGN KEY (city_id) REFERENCES city (id))

How to resolve it?

Today, let us see the steps followed by our Support Techs to resolve it:

There are two ways to fix the ERROR 1452 in MySQL database server:

1. Firstly, add the value into the referenced table
2. Then, disable the FOREIGN_KEY_CHECKS in the server

1. Add the value into the referenced table

The first option is to add the value we need to the referenced table.

In the example above, add the required id value to the City table.

Now we can insert a new row in the Buddies table with the city_id value that we inserted.

Disabling the foreign key check

2. Disable the FOREIGN_KEY_CHECKS variable in MySQL server.

We can check whether the variable is active or not by running the following query:

SHOW GLOBAL VARIABLES LIKE ‘FOREIGN_KEY_CHECKS’;

 — +——————–+——-+
— | Variable_name | Value |
— +——————–+——-+
— | foreign_key_checks | ON |
— +——————–+——-+

This variable causes MySQL to check any foreign key constraint added to our table(s) before inserting or updating.

We can disable the variable for the current session only or globally:

— set for the current session:
SET FOREIGN_KEY_CHECKS=0;
— set globally:
SET GLOBAL FOREIGN_KEY_CHECKS=0;

Now we can INSERT or UPDATE rows in our table without triggering a foreign key constraint fails.

After we are done with the manipulation query, we can set the FOREIGN_KEY_CHECKS active again by setting its value to 1:

— set for the current session:
SET FOREIGN_KEY_CHECKS=1;
— set globally:
SET GLOBAL FOREIGN_KEY_CHECKS=1;

Turning off FOREIGN_KEY_CHECKS variable will cause the city_id column to reference a NULL column in the City table.

It may cause problems when we need to perform a JOIN query later.

[Looking for a solution to another query? We are just a click away.]

Conclusion

To sum up, our skilled Support Engineers at Bobcares demonstrated how to resolve MySQL Error 1452.

PREVENT YOUR SERVER FROM CRASHING!

Never again lose customers to poor server speed! Let us help you.

Our server experts will monitor & maintain your server 24/7 so that it remains lightning fast and secure.

GET STARTED

  • Группа:
    Администратор
  • Сообщений:
    8995
  • Регистрация:
    20.02.2010

04.03.2011 01:05

Для многих своих таблиц Magento старается поддерживать целостность (непротиворечивость) данных между таблицами, и для этих целей использует ограничения для значений внешних ключей.
Выглядит это примерно так:

ALTER TABLE `directory_country_region_name`
	ADD CONSTRAINT `FK_DIRECTORY_REGION_NAME_REGION` 
		FOREIGN KEY (`region_id`) 
		REFERENCES `directory_country_region` (`region_id`) 
		ON DELETE CASCADE 
		ON UPDATE CASCADE
;

Если вы обновляете данные напрямую через SQL, вы можете столкнуться с сообщением «Foreign key constraint fails».
Сообщение означает, что обновляя записи одной таблицы, вы разорвали созданную командой «ADD CONSTRAINT» связь между её значениями и значениями другой таблицы, и MySQL видит, что целостность данных нарушена.
Соответственно, MySQL откажется выполнить вашу операцию и сообщит об ошибке «Foreign key constraint fails».

Если вы сознательно временно нарушаете целостность данных, то временно отключите проверку внешних ключей командой:

SET FOREIGN_KEY_CHECKS=0;

После выполнения команд, нарушающих ссылочную целостность и команд, восстанавливающих ссылочную целостность, верните контроль ссылочной целостности обратной командой:

SET FOREIGN_KEY_CHECKS=1;

Finding out why Foreign key creation fail

When MySQL is unable to create a Foreign Key, it throws out this generic error message:

ERROR 1215 (HY000): Cannot add foreign key constraint

– The most useful error message ever.

Fortunately, MySQL has this useful command that can give the actual reason about why it could not create the Foreign Key.

mysql> SHOW ENGINE INNODB STATUS;

That will print out lots of output but the part we are interested in is under the heading ‘LATEST FOREIGN KEY ERROR’:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
2020-08-29 13:40:56 0x7f3cb452e700 Error in foreign key constraint of table test_database/my_table:
there is no index in referenced table which would contain
the columns as the first columns, or the data types in the
referenced table do not match the ones in table. Constraint:
,
CONSTRAINT idx_name FOREIGN KEY (employee_id) REFERENCES employees (id)
The index in the foreign key in table is idx_name
Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-foreign-key-constraints.html for correct foreign key definition.

This output could give you some clue about the actual reason why MySQL could not create your Foreign Key

Reason #1 – Missing unique index on the referenced table

This is probably the most common reason why MySQL won’t create your Foreign Key constraint. Let’s look at an example with a new database and new tables:

In the all below examples, we’ll use a simple ‘Employee to Department” relationship:

mysql> CREATE DATABASE foreign_key_1;
Query OK, 1 row affected (0.00 sec)
mysql> USE foreign_key_1;
Database changed

mysql> CREATE TABLE employees(
    ->     id int,
    ->     name varchar(20),
    ->     department_id int
    -> );
Query OK, 0 rows affected (0.08 sec)

mysql> CREATE TABLE departments(
    ->     id int,
    ->     name varchar(20)
    -> );
Query OK, 0 rows affected (0.07 sec)

As you may have noticed, we have not created the table with PRIMARY KEY or unique indexes. Now let’s try to create Foreign Key constraint between employees.department_id column and departments.id column:

mysql> ALTER TABLE employees ADD CONSTRAINT fk_department_id FOREIGN KEY idx_employees_department_id (department_id) REFERENCES departments(id);
ERROR 1215 (HY000): Cannot add foreign key constraint

Let’s look at the detailed error:

mysql> SHOW ENGINE INNODB STATUS;
------------------------
LATEST FOREIGN KEY ERROR
------------------------
2020-08-31 09:25:13 0x7fddc805f700 Error in foreign key constraint of table foreign_key_1/#sql-5ed_49b:
FOREIGN KEY idx_employees_department_id (department_id) REFERENCES departments(id):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-foreign-key-constraints.html for correct foreign key definition.

This is because we don’t have any unique index on the referenced table i.e. departments. We have two ways of fixing this:

Option 1: Primary Keys

Let’s fix this by adding a primary key departments.id

mysql> ALTER TABLE departments ADD PRIMARY KEY (id);
Query OK, 0 rows affected (0.20 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE employees ADD CONSTRAINT fk_department_id FOREIGN KEY idx_employees_department_id (department_id) REFERENCES departments(id);
Query OK, 0 rows affected (0.19 sec)
Records: 0  Duplicates: 0  Warnings: 0

Option 2: Unique Index

mysql> CREATE UNIQUE INDEX idx_department_id ON departments(id);
Query OK, 0 rows affected (0.13 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE employees ADD CONSTRAINT fk_department_id FOREIGN KEY idx_employees_department_id (department_id) REFERENCES departments(id);
Query OK, 0 rows affected (0.21 sec)
Records: 0  Duplicates: 0  Warnings: 0

Reason #2 – Different data types on the columns

MySQL requires the columns involved in the foreign key to be of the same data types.

mysql> CREATE DATABASE foreign_key_1;
Query OK, 1 row affected (0.00 sec)

mysql> USE foreign_key_1;
Database changed

mysql> CREATE TABLE employees(
    ->     id int,
    ->     name varchar(20),
    ->     department_id int,
    ->     PRIMARY KEY (id)
    -> );
Query OK, 0 rows affected (0.06 sec)

mysql> CREATE TABLE departments(
    ->     id char(20),
    ->     name varchar(20),
    ->     PRIMARY KEY (id)
    -> );
Query OK, 0 rows affected (0.07 sec)

You may have noticed that employees.department_id is int while departments.id is char(20). Let’s try to create a foreign key now:

mysql> ALTER TABLE employees ADD CONSTRAINT fk_department_id FOREIGN KEY idx_employees_department_id (department_id) REFERENCES departments(id);
ERROR 1215 (HY000): Cannot add foreign key constraint

Let’s fix the type of departments.id and try to create the foreign key again:

mysql> ALTER TABLE departments MODIFY id INT;
Query OK, 0 rows affected (0.18 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE employees ADD CONSTRAINT fk_department_id FOREIGN KEY idx_employees_department_id (department_id) REFERENCES departments(id);
Query OK, 0 rows affected (0.26 sec)
Records: 0  Duplicates: 0  Warnings: 0

It works now!

Reason #3 – Different collation/charset type on the table

This is a surprising reason and hard to find out. Let’s create two tables with different collation (or also called charset):

Let’s start from scratch to explain this scenario:

mysql> CREATE DATABASE foreign_key_1;                                                                                        Query OK, 1 row affected (0.00 sec)

mysql> USE foreign_key_1;                                                                                                    Database changed

mysql> CREATE TABLE employees(
    ->     id int,
    ->     name varchar(20),
    ->     department_id int,
    ->     PRIMARY KEY (id)
    -> ) ENGINE=InnoDB CHARACTER SET=utf8;
Query OK, 0 rows affected (0.06 sec)

mysql> CREATE TABLE departments(
    ->     id int,
    ->     name varchar(20),
    ->     PRIMARY KEY (id)
    -> ) ENGINE=InnoDB CHARACTER SET=latin1;
Query OK, 0 rows affected (0.08 sec)

You may notice that we are using a different character set (utf8 and latin1` for both these tables. Let’s try to create the foreign key:

mysql> ALTER TABLE employees ADD CONSTRAINT fk_department_id FOREIGN KEY idx_employees_department_id (department_id) REFERENCES departments(id);
ERROR 1215 (HY000): Cannot add foreign key constraint

It failed because of different character sets. Let’s fix that.

mysql> SET foreign_key_checks = 0; ALTER TABLE departments CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; SET foreign_key_checks = 1;
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.18 sec)
Records: 0  Duplicates: 0  Warnings: 0

Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE employees ADD CONSTRAINT fk_department_id FOREIGN KEY idx_employees_department_id (department_id) REFERENCES departments(id);
Query OK, 0 rows affected (0.20 sec)
Records: 0  Duplicates: 0  Warnings: 0

If you have many tables with a different collation/character set, use this script to generate a list of commands to fix all tables at once:

mysql --database=your_database -B -N -e "SHOW TABLES" | awk '{print "SET foreign_key_checks = 0; ALTER TABLE", $1, "CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; SET foreign_key_checks = 1; "}'

Reason #4 – Different collation types on the columns

This is a rare reason, similar to reason #3 above but at a column level.

Let’s try to reproduce this from scratch:

mysql> CREATE DATABASE foreign_key_1;                                                                                        Query OK, 1 row affected (0.00 sec)

mysql> USE foreign_key_1;                                                                                                    Database changed

mysql> CREATE TABLE employees(
    ->     id int,
    ->     name varchar(20),
    ->     department_id char(26) CHARACTER SET utf8,
    ->     PRIMARY KEY (id)
    -> );
Query OK, 0 rows affected (0.07 sec)

mysql> CREATE TABLE departments(
    ->     id char(26) CHARACTER SET latin1,
    ->     name varchar(20),
    ->     PRIMARY KEY (id)
    -> );
Query OK, 0 rows affected (0.08 sec)

We are using a different character set for employees.department_id and departments.id (utf8 and latin1). Let’s check if the Foreign Key can be created:

mysql> ALTER TABLE employees ADD CONSTRAINT fk_department_id FOREIGN KEY idx_employees_department_id (department_id) REFERENCES departments(id);
ERROR 1215 (HY000): Cannot add foreign key constraint

Nope, as expected. Let’s fix that by changing the character set of departments.id to match with employees.department_id:

mysql> ALTER TABLE departments MODIFY id CHAR(26) CHARACTER SET utf8;
Query OK, 0 rows affected (0.20 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> ALTER TABLE employees ADD CONSTRAINT fk_department_id FOREIGN KEY idx_employees_department_id (department_id) REFERENCES departments(id);
Query OK, 0 rows affected (0.20 sec)
Records: 0  Duplicates: 0  Warnings: 0

It works now!

Reason #5 -Inconsistent data

This would be the most obvious reason. A foreign key is to ensure that your data remains consistent between the parent and the child table. So when you are creating the foreign key, the existing data is expected to be already consistent.

Let’s setup some inconsistent data to reproduce this problem:

mysql> CREATE DATABASE foreign_key_1;                                                                                        Query OK, 1 row affected (0.00 sec)

mysql> USE foreign_key_1;                                                                                                    Database changed

mysql> CREATE TABLE employees(
    ->     id int,
    ->     name varchar(20),
    ->     department_id int,
    ->     PRIMARY KEY (id)
    -> );
Query OK, 0 rows affected (0.06 sec)

mysql> CREATE TABLE departments(
    ->     id int,
    ->     name varchar(20),
    ->     PRIMARY KEY (id)
    -> );
Query OK, 0 rows affected (0.08 sec)

Let’s insert a department_id in employees table that will not exist in departments.id:

mysql> INSERT INTO employees VALUES (1, 'Amber', 145);
Query OK, 1 row affected (0.01 sec)

Let’s create a foreign key now and see if it works:

mysql> ALTER TABLE employees ADD CONSTRAINT fk_department_id FOREIGN KEY idx_employees_department_id (department_id) REFERENCES departments(id);

ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`foreign_key_1`.`#sql-5ed_49b`, CONSTRAINT `fk_department_id` FOREIGN KEY (`department_id`) REFERENCES `departments` (`id`))

This error message is atleast more useful. We can fix this in two ways. Either by adding the missing department in departments table or by deleting all the employees with the missing department. We’ll do the first option now:

mysql> INSERT INTO departments VALUES (145, 'HR');
Query OK, 1 row affected (0.00 sec)

Let’s try to create the Foreign Key again:

mysql> ALTER TABLE employees ADD CONSTRAINT fk_department_id FOREIGN KEY idx_employees_department_id (department_id) REFERENCES departments(id);
Query OK, 1 row affected (0.24 sec)
Records: 1  Duplicates: 0  Warnings: 0

It worked this time.

So we have seen 5 different ways a Foreign Key creation can fail and possible solutions of how we can fix them. If you have encountered a reason not listed above, add them in the comments.

If you are using MySQL 8.x, the error message will be a little different:

SQLSTATE[HY000]: General error: 3780 Referencing column 'column' and referenced column 'id' in foreign key constraint 'idx_column_id' are incompatible. 

Привет, посетитель сайта ZametkiNaPolyah.ru! Продолжаем изучать базы данных и наше знакомство с библиотекой SQLite3. В реляционных базах данных, вернее, в реляционных СУБД есть множество приемов, которые позволяют обеспечить целостность данных, мы уже разобрались с ограничением уровня столбца и первичным ключом, который является одновременно и индексом таблицы базы данных, позволяющим значительно ускорить выборку данных из базы данных, и правилом, которое четко выполняет SQLite. В этой записи мы поговорим про еще одно ограничение уровня таблиц: внешний ключ или FOREIGN KEY.

Внешние ключи в базах данных SQLite: FOREIGN KEY в SQLite3

Внешние ключи в базах данных SQLite: FOREIGN KEY в SQLite3

Из этой записи вы узнаете как работает и для чего нужны внешние ключи в базах данных SQLite3. Познакомитесь с синтаксисом FROREIGN KEY в SQLite. А так же узнаете, как реализовать связи один ко многим и многие ко многим между таблицами базы данных под управлением SQLite при помощи внешних ключей. Но, стоит заметить, что вы сможете реализовать данные связи и без использования FOREIGN KEY, но в этом случае вы никак не обеспечите целостность данных в ваших таблицах.

Работа внешних ключей в базах данных SQLite: FOREIGEN KEY и REFERENCE в SQLite3

Содержание статьи:

  • Работа внешних ключей в базах данных SQLite: FOREIGEN KEY и REFERENCE в SQLite3
  • Реализация связи один ко многим в базах данных SQLite. Пример связи один ко многим и FOREIGEN KEY в SQLite
  • Реализация связи многие ко многим в базах данных SQLite3
  • Немного о логике внешних ключей в SQLite

Внешний ключ или FOREIGN KEY – это ограничение уровня таблицы в реляционных базах данных, в том числе и в базе данных SQLite3. Внешние ключи определяют правила, по которым будут связаны таблицы в базах данных SQLite. Но, кроме того, что внешние ключи определяют то, как будут связаны таблицы в базах данных SQLite3, они еще нужны для обеспечения целостности данных в базах данных.

В SQLite внешний ключ объявляется при помощи конструкции FOREIGN KEY, а таблица, на которую ссылается внешний ключ указывается после ключевого слово REFERENCE. Обратите внимание: указывается не только таблица, но и столбец, на который идет ссылка. Ниже вы можете увидеть изображение, на котором показан синтаксис использования внешнего ключа в базах данных SQLite, вернее синтаксис конструкции REFERENCE.

Синтаксис ограничения внешнего ключа в базах данных SQLite3

Синтаксис ограничения внешнего ключа в базах данных SQLite3

Правила использования внешнего ключа не очень сложные, но давайте разберемся с тем, как реализован внешний ключ в SQLite3 и его конструкции: FOREIGEN KEY и REFEERENCE. Обратите внимание: когда вы связываете таблицы при помощи внешнего ключа одна таблица является родительской, а вторая таблица является дочерней. Внешний ключ всегда ссылается на родительскую таблиц, другими словами конструкция FOREIGN KEY и REFERENCE указывается в дочерней таблице.

Подведем итог: внешний ключ в базах данных SQLite необходим для реализации связей между таблицами. FOREIGEN KEY позволяет реализовывать связи между таблицами в базах данных. Конструкция REFERENCE используется для указания ссылки на родительскую таблицу. Внешний ключ обеспечивает целостность данных между двумя таблицами и необходим для нормализации базы данных. Вторая нормальная форма и третья нормальная форма не могут быть реализованы без внешнего ключа. Вернее будет сказать: мы можем организовать связи между таблицами без внешнего ключа, но проверка правил при этом выполняться не будет.

Давайте рассмотрим несколько практических примеров реализации внешнего ключа в базах данных SQLite. Мы реализуем два типа связи: связь один ко многим и связь многие ко многим.

Реализация связи один ко многим в базах данных SQLite. Пример связи один ко многим и FOREIGEN KEY в SQLite

Давайте реализуем связь один ко многим при помощи внешнего ключа, для этого воспользуемся конструкциями FORIGEN KEY и REFERENCE. Мы будем связывать при помощи внешнего ключа две таблицы: таблицу авторов и таблицу книг, поэтому давайте договоримся о допущение, что один автор может написать много книг, но у книги может быть только один автор.

Чтобы реализовать связь один ко многим, нам нужно воспользоваться конструкцией FOREIGEN KEY и REFERENCE при создании таблицы при помощи команды CREATE.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

PRAGMA foreign_keys=on;

CREATE TABLE books(

Id INTEGER PRIMARY KEY,

title TEXT NOT NULL,

count_page INTEGER NOT NULL CHECK (count_page >0),

price REAL CHECK (price >0),

auth_id INTEGER NOT NULL,

FOREIGN KEY (auth_id) REFERENCES auth(id)

);

CREATE TABLE auth(

id INTEGER PRIMARY KEY,

name TEXT NOT NULL,

age INTEGER  CHECK (age >16)

);

Здесь нам нужно дать пояснение к том, как мы создали внешний ключ для базы данных. Во-первых, в SQLite3 по умолчанию отключена поддержка внешних ключей, команда PRAGMA позволяет включить внешние ключи в базах данных SQLite. Во-вторых, помимо внешнего ключа наши таблицы имеют ограничения уровня столбца. Третье, столбец который ссылается и столбец, на который ссылается, должны иметь одинаковый тип данных, это закон реляционных баз данных.

Если столбцы будут иметь разные типы данных внешний ключ не будет работать. Скорее всего, другие СУБД вам даже не дадут возможность создать такой внешний ключ, но SQLite имеет динамическую типизацию данных, поэтому внешний ключ будет создан.

Далее: конструкция FOREIGEN KEY объявляет о том, что столбец auth_id является ссылкой, а конструкция REFERENCE указывает, что столбец auth_id является ссылкой на столбец id таблицы auth. Таким нехитрым образом мы реализовали связь один ко многим в базе данных SQLite при помощи внешнего ключа.

Давайте теперь добавим строки в таблицу auth нашей базы данных, это можно сделать командой INSERT:

INSERT INTO auth (id, name, age)

VALUES (1, ‘Джек Лондон’, 40);

INSERT INTO auth (id, name, age)

VALUES (2, ‘Лев Толстой’, 82);

Добавлять данные при создании внешнего ключа и использовании FOREIGN KEY в нашем случае удобнее сперва в ту таблицу, на которую идет ссылка. Теперь добавим строки в таблицу books и укажем значения для нашего внешнего ключа.

INSERT INTO books (id, title, count_page, price, auth_id)

VALUES (1, ‘Белый клык’, 287, 300.00, 1);

INSERT INTO books (id, title, count_page, price, auth_id)

VALUES (2, ‘Война и мир’, 806, 780.00, 2);

Поскольку связь один ко многим, по нашей договоренности: один автор может написать много книг, добавим еще одно произведение Джека Лондона:

INSERT INTO books (id, title, count_page, price, auth_id)

VALUES (3, ‘Зов предков’, 121, 160.00, 1);

А теперь давайте посмотрим, что нам дает связь один ко многим, реализованная благодаря внешнему ключу, и как действует ограничение FOREIGEN KEY.

INSERT INTO books (id, title, count_page, price, auth_id)

VALUES (4, ‘Белый клык’, 121, 160.00, 3);

Этот SQL запрос INSERT не будет выполнен в SQLite3, поскольку действует ограничение внешнего ключа, мы получим ошибку: Error: FOREIGN KEY constraint failed. В таблице справочнике с авторами нет значения id = 3, SQLite это проверил и сказал нам, что мы не правы, что у  него есть FOREIGN KEY, который ничего не знает про автора с id = 3. Так обеспечивается целостность данных и так мы избавляемся от аномалии добавления данных в базах данных.

В нашем случае, если мы попробуем передать внешнему ключу значение NULL, то строка в таблицу не добавится, так как действует ограничение уровня столбца NOT NULL, но если бы этого ограничения не было, SQLite спокойно и честно добавил значение NULL, как ссылку в таблицу books, это может нарушить целостность ваших данных, поэтому будьте аккуратны, но это нельзя считать ошибкой, например, есть книги, автор которых неизвестен.

Попробуем изменить данные в таблицах, связанных при помощи внешнего ключа. Для этого воспользуемся командой UPDATE:

UPDATE books SET auth_id = 4 WHERE title = ‘Белый клык’;

SQLite не дала нам изменить значение auth_id на 4, так как в таблице auth нет авторов с id = 4 и это благодаря наличию внешнего ключа. Ошибка в SQLite будет содержать следующий текст: Error: FOREIGN KEY constraint failed. В дальнейшем мы рассмотрим каскадное обновление данных при помощи команды ON UPDATE.

Нам осталось использовать последнюю команду из группы манипуляции данными, чтобы убедиться, что внешние ключи в SQLite действительно обеспечивают целостность данных в базе данных. Попробуем удалить данные из таблицы, для этого есть команда DELETE.

DELETE FROM auth WHERE name = ‘Лев Толстой’;

Сделать у нас это не получится, потому что сработает ограничение внешнего ключа, мы не можем удалить данные из таблицы справочника авторов, пока на них ссылаются значения из таблицы книг. Ошибка будет следующей: Error: FOREIGN KEY constraint failed.

Чтобы удалить данные из справочника, мы сперва должны удалить данные из таблицы которая ссылается на справочник, давайте это реализуем.

DELETE FROM books WHERE auth_id = 2;

DELETE FROM auth WHERE name = ‘Лев Толстой’;

Теперь мы удалили упоминание об авторе в таблице книг, а затем смогли удалить данные об авторе из таблицы auth, по-другому удалить данные из справочника мы не сможем: сперва удаляем данные из ссылающейся таблицы, а потом удаляем данные из таблицы, на которую ссылаемся – это правило внешнего ключа, которое обеспечивает целостность данных и защищает нас от аномалии удаления данных.

Про команду SELECT и то, как она работает с таблицами, которые используют внешние ключи, мы поговорим отдельно, так как это большая и требующая некоторых дополнительных усилий тема.

Сейчас нам важно понимать, что конструкция FOREIGEN KEY REFERENCE организует связь между таблицами базы данных, а также то, что внешний ключ очень тесно связан с понятием нормализации данных в базе данных. FOREIGEN KEY – это ограничения, которые заставляют SQLite проверять выполнение набора определенных правил, которые позволяют избежать аномалии модификации, удаления и обновления данных в таблицах базах данных.

Реализация связи многие ко многим в базах данных SQLite3

В принципе, мы уже сказали всё, что можно о внешних ключах в базах данных SQLite и разобрали особенности работы FOREIGEN KEY и REFERENCE в SQLite3. Раньше мы намеренно упрощали примеры, когда говорили про третью нормальную форму и когда разговаривали про особенности внешних ключей.

Давайте теперь исправим это упущение и будем считать, что одну книгу может написать много авторов и один автор может написать много книг. Реализуем связь многие ко многим в базах данных SQLite3 при помощи внешнего ключа.

Вы, наверное, помните, что для реализации связи многие ко многим нам необходимо создавать третью таблицу, ее можно назвать результирующей, а можно назвать и промежуточной. Мы назовем эту таблицу auth_book.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

PRAGMA foreign_keys=on;

CREATE TABLE books(

Id INTEGER PRIMARY KEY,

title TEXT NOT NULL,

count_page INTEGER NOT NULL CHECK (count_page >0),

price REAL CHECK (price >0)

);

CREATE TABLE auth(

id INTEGER PRIMARY KEY,

name TEXT NOT NULL,

age INTEGER  CHECK (age >16)

);

CREATE TABLE auth_book (

auth_id INTEGER NOT NULL,

books_id INTEGER NOT NULL,

FOREIGN KEY (auth_id) REFERENCES auth(id)

FOREIGN KEY (books_id) REFERENCES books(id)

);

Никаких особых хитростей при реализации связи в базах данных SQLite, да и любых других реляционных базах данных нет. Мы создали третью таблицу, в которой есть два столбца и оба этих столбца являются внешними ключами. Столбец auth_id является ссылкой на таблицу авторов, столбец books_id – это ссылка на таблицу книг. Добавляем данные в таблицы командой INSERT.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

Сперва добавим несколько строк в таблицу книг

INSERT INTO books (id, title, count_page, price)

VALUES (1, ‘Белый клык’, 287, 300.00);

INSERT INTO books (id, title, count_page, price)

VALUES (2, ‘Война и мир’, 806, 780.00);

Затем добавим несколько авторов

INSERT INTO auth (id, name, age)

VALUES (1, ‘Джек Лондон’, 40);

INSERT INTO auth (id, name, age)

VALUES (2, ‘Лев Толстой’, 82);

Мы добавили книги и авторов из предыдущего примера

Давайте добавим новую книгу

INSERT INTO books (id, title, count_page, price)

VALUES (3, 12 стульев’, 516, 480.00);

И добавим авторов, так 12 стульев была написана в соавторстве

Затем добавим несколько авторов

INSERT INTO auth (id, name, age)

VALUES (3, ‘Илья Ильф’, 39);

INSERT INTO auth (id, name, age)

VALUES (4, ‘Евгений Петров’, 38);

Мы подготовили таблицы, которые, на первый взгляд никак не связаны между собой, теперь давайте свяжем их связью многие ко многим, добавив нужные значения в столбцы FOREIGEN KEY таблицы auth_book.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

Связываем таблицы auth и book

для этого наполним данными результирующую таблицу

INSERT INTO auth_book (auth_id, books_id)

VALUES (1, 1);

INSERT INTO auth_book (auth_id, books_id)

VALUES (2, 2);

INSERT INTO auth_book (auth_id, books_id)

VALUES (3, 3);

INSERT INTO auth_book (auth_id, books_id)

VALUES (4, 3);

Хочу обратить ваше внимание на то, что SQLite и слышать не слышала про Льва Толстого, Джека Лондона и Ильфа с Петровым, она лишь проверяет работоспособность ссылок, ответственность за наполнение таблиц лежит на операторе. При таком подходе вы легко можете сказать, что Джек Лондон написал Войну и мир:

Говорим SQLite о том, что Джек Лондон написал Войну и мир

INSERT INTO auth_book (auth_id, books_id)

VALUES (1, 2);

С точки логики SQLite никакой ошибки нет, с точки зрения человека – ошибка есть. Внешние ключи никак не могут проверить смысл, который заложен в данных, они лишь проверяют и ограничивают логику работы базы данных. Но не все так страшно, когда мы начнем работать с триггерами, мы посмотрим, как при помощи триггера сделать так, чтобы результирующая таблица при организации связи многие ко многим с помощью FOREIGN KEY заполнялась автоматически, это будет дополнительным уровнем обеспечения целостности данных в базах данных.

Немного о логике внешних ключей в SQLite

Когда мы рассматривали третью и вторую нормальные формы, мы ничего не упоминали про внешние ключи и про то, что они реализуют связи между таблицами. Тогда мы говорили, что справочник является дочерней таблицей, а вот таблица со ссылками (со столбцом FOREIGEN KEY) является родительской. С одной стороны, мы правильно говорим, до тех пор, пока не сталкиваемся со связью многие ко многим, ведь нельзя же результирующую таблицу называть родительской…

Поэтому в базах данных SQLite разработчики четко обозначили терминологию:

  1. Родительская таблица — это таблица, на которую ссылается внешний ключ (FOREIGN KEY).
  2. Дочерняя таблица — это таблица, к которой применяется ограничение внешнего ключа.
  3. Родительский ключ — это один или несколько столбцов родительской таблицы, на которые ссылается внешний ключ (FOREIGN KEY).
  4. Дочерний ключ — это один или несколько столбцов дочерней таблицы, значения которых ограничиваются внешним ключом и которые перечисляются после ключевой фразы REFERENCES.

На самом деле, вам нужно выбрать ту терминологию, которую вам легче воспринимать, мне легче воспринимать так: таблица справочник – дочерняя таблица, таблица, которая ссылается на справочник – родительская таблица.

Важно, чтобы другие вас понимали, благо, язык SQL универсальный и все понимают, что FOREIGN KEY – это внешний ключ, который обеспечивает целостность данных. FOREIGN KEY, как и первичный ключ или PRIMARY KEY, имеет синтаксис, который позволяет записывать данное ограничение, как ограничение уровня столбца.

Introduction

A foreign key is a field (or collection of fields) in one table that uniquely identifies a row of another table. The table containing the foreign key is called the child table, and the table containing the candidate key is called the referenced or parent table. The purpose of the foreign key is to identify a particular row of the referenced table. Therefore, it is required that the foreign key is equal to the candidate key in some row of the primary table, or else have no value (the NULL value). This is called a referential integrity constraint between the two tables. Because violations of these constraints can be the source of many database problems, most database management systems provide mechanisms to ensure that every non-null foreign key corresponds to a row of the referenced table. Consider following simple example:

create table parent (
    id int not null primary key,
    name char(80)
) engine=innodb;

create table child (
    id int not null,
    name char(80),
    parent_id int, 
    foreign key(parent_id) references parent(id)
) engine=innodb;

As far as I know, the following storage engines for MariaDB and/or MySQL support foreign keys:

  • InnoDB (both innodb_plugin and XtraDB)
  • PBXT (https://mariadb.com/kb/en/mariadb/about-pbxt/)
  • SolidDB for MySQL (http://sourceforge.net/projects/soliddb/)
  • ScaleDB (https://mariadb.com/kb/en/mariadb/scaledb/ and http://scaledb.com/pdfs/TechnicalOverview.pdf)
  • MySQL Cluster NDB 7.3 or later (https://dev.mysql.com/doc/refman/5.6/en/mysql-cluster-ndb-innodb-engines.html)

MariaDB foreign key syntax is documented at https://mariadb.com/kb/en/mariadb/foreign-keys/ (and MySQL at http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html). While most of the syntax is parsed and checked when the CREATE TABLE or ALTER TABLE clause is parsed, there are still several error cases that can happen inside InnoDB. Yes, InnoDB has its own internal foreign key constraint parser (in dict0dict.c function dict_create_foreign_constraints_low()).

However, the error messages shown in CREATE or ALTER TABLE, and SHOW WARNINGS in versions of MariaDB prior to 5.5.45 and 10.0.21 are not very informative or clear. There are additional error messages if you issue SHOW ENGINE INNODB STATUS, which help, but were not an ideal solution. In this blog I’ll present a few of the most frequent error cases using MariaDB 5.5.44 and how these error messages are improved in MariaDB 5.5.45 and 10.0.21. I will use the default InnoDB (i.e. XtraDB) but innodb_plugin works very similarly.

Constraint name not unique

Foreign name constraint names must be unique in a database. However, the error message is unclear and leaves a lot unclear:

--------------
CREATE TABLE t1 (
  id int(11) NOT NULL PRIMARY KEY,
  a int(11) NOT NULL,
  b int(11) NOT NULL,
  c int not null,
  CONSTRAINT test FOREIGN KEY (b) REFERENCES t1 (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
--------------
Query OK, 0 rows affected (0.45 sec)

--------------
CREATE TABLE t2 (
id int(11) NOT NULL PRIMARY KEY,
a int(11) NOT NULL,
b int(11) NOT NULL,
c int not null,
CONSTRAINT mytest FOREIGN KEY (c) REFERENCES t1(id),
CONSTRAINT test FOREIGN KEY (b) REFERENCES t2 (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
--------------

ERROR 1005 (HY000): Can't create table `test`.`t2` (errno: 121 "Duplicate key on write or update")
--------------
show warnings
--------------

+---------+------+--------------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------------------------------------+
| Error | 1005 | Can't create table `test`.`t2` (errno: 121 "Duplicate key on write or update") |
| Warning | 1022 | Can't write; duplicate key in table 't2' |
+---------+------+--------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

These messages are not very helpful because there are two foreign key constraints. Looking into SHOW ENGINE INNODB STATUS we get a better message:

show engine innodb status
--------------
------------------------
LATEST FOREIGN KEY ERROR
------------------------
2015-07-30 12:37:48 7f44a1111700 Error in foreign key constraint creation for table `test`.`t2`.
A foreign key constraint of name `test`.`test`
already exists. (Note that internally InnoDB adds 'databasename'
in front of the user-defined constraint name.)
Note that InnoDB's FOREIGN KEY system tables store
constraint names as case-insensitive, with the
MySQL standard latin1_swedish_ci collation. If you
create tables or databases whose names differ only in
the character case, then collisions in constraint
names can occur. Workaround: name your constraints
explicitly with unique names.

In MariaDB 5.5.45 and 10.0.21, the message is clearly improved:

CREATE TABLE t1 (
  id int(11) NOT NULL PRIMARY KEY,
  a int(11) NOT NULL,
  b int(11) NOT NULL,
  c int not null,
  CONSTRAINT test FOREIGN KEY (b) REFERENCES t1 (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
--------------

Query OK, 0 rows affected (0.14 sec)

--------------
CREATE TABLE t2 (
  id int(11) NOT NULL PRIMARY KEY,
  a int(11) NOT NULL,
  b int(11) NOT NULL,
  c int not null,
  CONSTRAINT mytest FOREIGN KEY (c) REFERENCES t1(id),
  CONSTRAINT test FOREIGN KEY (b) REFERENCES t2 (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
--------------

ERROR 1005 (HY000): Can't create table 'test.t2' (errno: 121)
--------------
show warnings
--------------

+---------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                                                                                                                                                                                     |
+---------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning |  121 | Create or Alter table `test`.`t2` with foreign key constraint failed. Foreign key constraint `test/test` already exists on data dictionary. Foreign key constraint names need to be unique in database. Error in foreign key definition: CONSTRAINT `test` FOREIGN KEY (`b`) REFERENCES `test`.`t2` (`id`). |
| Error   | 1005 | Can't create table 'test.t2' (errno: 121)                                                                                                                                                                                                                                                                   |
+---------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

No index

There should be an index for columns in a referenced table that contains referenced columns as the first columns.

create table t1(a int, b int, key(b)) engine=innodb
--------------
Query OK, 0 rows affected (0.46 sec)

--------------
create table t2(a int, b int, constraint b foreign key (b) references t1(b), constraint a foreign key a (a) references t1(a)) engine=innodb
--------------

ERROR 1005 (HY000): Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
--------------
show warnings
--------------

+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning | 150 | Create table 'test/t2' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
|
| Error | 1005 | Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") |
| Warning | 1215 | Cannot add foreign key constraint |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.00 sec)

Fine but again we have no idea which foreign key it was. As before, there is a better message in the SHOW ENGINE INNODB STATUS output:

LATEST FOREIGN KEY ERROR
------------------------
2015-07-30 13:44:31 7f30e1520700 Error in foreign key constraint of table test/t2:
 foreign key a (a) references t1(a)) engine=innodb:
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html
for correct foreign key definition.

In MariaDB 5.5.45 and 10.0.21, the message is clearly improved:

create table t1(a int, b int, key(b)) engine=innodb
--------------

Query OK, 0 rows affected (0.16 sec)

--------------
create table t2(a int, b int, constraint b foreign key (b) references t1(b), constraint a foreign key a (a) references t1(a)) engine=innodb
--------------

ERROR 1005 (HY000): Can't create table 'test.t2' (errno: 150)
--------------
show warnings
--------------

+---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                                                                                                                |
+---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning |  150 | Create  table '`test`.`t2`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns. Error close to  foreign key a (a) references t1(a)) engine=innodb. |
| Error   | 1005 | Can't create table 'test.t2' (errno: 150)                                                                                                                                                                                              |
+---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

Referenced table not found

A table that is referenced on foreign key constraint should exist in InnoDB data dictionary. If not:

create table t1 (f1 integer primary key) engine=innodb
--------------

Query OK, 0 rows affected (0.47 sec)

--------------
alter table t1 add constraint c1 foreign key (f1) references t11(f1)
--------------

ERROR 1005 (HY000): Can't create table `test`.`#sql-2612_2` (errno: 150 "Foreign key constraint is incorrectly formed")
--------------
show warnings
--------------

+---------+------+-----------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                             |
+---------+------+-----------------------------------------------------------------------------------------------------+
| Error   | 1005 | Can't create table `test`.`#sql-2612_2` (errno: 150 "Foreign key constraint is incorrectly formed") |
| Warning | 1215 | Cannot add foreign key constraint                                                                   |
+---------+------+-----------------------------------------------------------------------------------------------------+
show engine innodb status
--------------
LATEST FOREIGN KEY ERROR
------------------------
2015-07-30 13:44:34 7f30e1520700 Error in foreign key constraint of table test/#sql-2612_2:
 foreign key (f1) references t11(f1):
Cannot resolve table name close to:
(f1)

Both messages are first referring to an internal table name and the foreign key error message is referring to an incorrect name. In MariaDB 5.5.45 and 10.0.21, the message is clearly improved:

create table t1 (f1 integer primary key) engine=innodb
--------------

Query OK, 0 rows affected (0.11 sec)

--------------
alter table t1 add constraint c1 foreign key (f1) references t11(f1)
--------------

ERROR 1005 (HY000): Can't create table 'test.#sql-2b40_2' (errno: 150)
--------------
show warnings
--------------

+---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                                                    |
+---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning |  150 | Alter  table `test`.`t1` with foreign key constraint failed. Referenced table `test`.`t11` not found in the data dictionary close to  foreign key (f1) references t11(f1). |
| Error   | 1005 | Can't create table 'test.#sql-2b40_2' (errno: 150)                                                                                                                         |
+---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

--------------
show engine innodb status
--------------
150730 13:50:36 Error in foreign key constraint of table `test`.`t1`:
Alter  table `test`.`t1` with foreign key constraint failed. Referenced table `test`.`t11` not found in the data dictionary close to  foreign key (f1) references t11(f1).

Temporary tables

Temporary tables can’t have foreign key constraints because temporary tables are not stored to the InnoDB data dictionary.

create temporary table t2(a int, foreign key(a) references t1(a)) engine=innodb
--------------

ERROR 1005 (HY000): Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
--------------
show warnings
--------------

+---------+------+--------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                    |
+---------+------+--------------------------------------------------------------------------------------------+
| Error   | 1005 | Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") |
| Warning | 1215 | Cannot add foreign key constraint                                                          |
+---------+------+--------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

--------------
show engine innodb status
--------------
LATEST FOREIGN KEY ERROR
------------------------
2015-07-30 13:44:35 7f30e1520700 Error in foreign key constraint of table tmp/#sql2612_2_1:
foreign key(a) references t1(a)) engine=innodb:
Cannot resolve table name close to:
(a)) engine=innodb

--------------
alter table t1 add foreign key(b) references t1(a)
--------------

ERROR 1005 (HY000): Can't create table `test`.`#sql-2612_2` (errno: 150 "Foreign key constraint is incorrectly formed")
--------------
show warnings
--------------

+---------+------+-----------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                             |
+---------+------+-----------------------------------------------------------------------------------------------------+
| Error   | 1005 | Can't create table `test`.`#sql-2612_2` (errno: 150 "Foreign key constraint is incorrectly formed") |
| Warning | 1215 | Cannot add foreign key constraint                                                                   |
+---------+------+-----------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

These error messages do not really help the user, because the actual reason for the error is not printed and the foreign key error references an internal table name. In MariaDB 5.5.45 and 10.0.21 this is clearly improved:

create temporary table t1(a int not null primary key, b int, key(b)) engine=innodb
--------------

Query OK, 0 rows affected (0.04 sec)

--------------
create temporary table t2(a int, foreign key(a) references t1(a)) engine=innodb
--------------

ERROR 1005 (HY000): Can't create table 'test.t2' (errno: 150)
--------------
show warnings
--------------

+---------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                                                             |
+---------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning |  150 | Create  table `tmp`.`t2`Ï with foreign key constraint failed. Referenced table `tmp`.`t1` not found in the data dictionary close to foreign key(a) references t1(a)) engine=innodb.  |
| Error   | 1005 | Can't create table 'test.t2' (errno: 150)                                                                                                                                           |
+---------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

--------------
alter table t1 add foreign key(b) references t1(a)
--------------

ERROR 1005 (HY000): Can't create table 'test.#sql-2b40_2' (errno: 150)
--------------
show warnings
--------------

+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                                             |
+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning |  150 | Alter  table `tmp`.`t1`Ï with foreign key constraint failed. Referenced table `tmp`.`t1` not found in the data dictionary close to foreign key(b) references t1(a).  |
| Error   | 1005 | Can't create table 'test.#sql-2b40_2' (errno: 150)                                                                                                                  |
+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

Column count does not match

There should be exactly the same number of columns in both the foreign key column list and the referenced column list. However, this currently raises the following error:

create table t1(a int not null primary key, b int, key(b)) engine=innodb
--------------

Query OK, 0 rows affected (0.17 sec)

--------------
alter table t1 add foreign key(a,b) references t1(a)
--------------

ERROR 1005 (HY000): Can't create table 'test.#sql-4856_1' (errno: 150)
--------------
show warnings
--------------

+-------+------+----------------------------------------------------+
| Level | Code | Message |
+-------+------+----------------------------------------------------+
| Error | 1005 | Can't create table 'test.#sql-4856_1' (errno: 150) |
+-------+------+----------------------------------------------------+
1 row in set (0.00 sec)

-----------------+
show engine innodb status;
-----------------+
LATEST FOREIGN KEY ERROR
------------------------
150730 15:15:57 Error in foreign key constraint of table test/#sql-4856_1:
foreign key(a,b) references t1(a):
Syntax error close to: 2015-07-30 13:44:35 7f30e1520700 Error in foreign key constraint of table tmp/#sql2612_2_2: foreign key(b) references t1(a): Cannot resolve table name close to: (a)

The error message is not clear and the foreign key error refers to an internal table name. In MariaDB 5.5.45 and 10.0.21 there is additional information:

create table t1(a int not null primary key, b int, key(b)) engine=innodb
--------------

Query OK, 0 rows affected (0.14 sec)

--------------
alter table t1 add foreign key(a,b) references t1(a)
--------------

ERROR 1005 (HY000): Can't create table 'test.#sql-2b40_2' (errno: 150)
--------------
show warnings
--------------

+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning | 150 | Alter table `test`.`t1` with foreign key constraint failed. Foreign key constraint parse error in foreign key(a,b) references t1(a) close to ). Too few referenced columns, you have 1 when you should have 2. |
| Error | 1005 | Can't create table 'test.#sql-2b40_2' (errno: 150) |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

Incorrect cascading

A user may define a foreign key constraint with ON UPDATE SET NULL or ON DELETE SET NULL. However, this requires that the referenced columns are not defined as NOT NULL. Currently, the error message on this situation is:

create table t1 (f1 integer not null primary key) engine=innodb
--------------

Query OK, 0 rows affected (0.40 sec)

--------------
alter table t1 add constraint c1 foreign key (f1) references t1(f1) on update set null
--------------

ERROR 1005 (HY000): Can't create table `test`.`#sql-2612_2` (errno: 150 "Foreign key constraint is incorrectly formed")
--------------
show warnings
--------------

+---------+------+-----------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                             |
+---------+------+-----------------------------------------------------------------------------------------------------+
| Error   | 1005 | Can't create table `test`.`#sql-2612_2` (errno: 150 "Foreign key constraint is incorrectly formed") |
| Warning | 1215 | Cannot add foreign key constraint                                                                   |
+---------+------+---------------------------------------------------------------------------------------------

--------+
show engine innodb status;
--------+
LATEST FOREIGN KEY ERROR
------------------------
2015-07-30 13:44:37 7f30e1520700 Error in foreign key constraint of table test/#sql-2612_2:
 foreign key (f1) references t1(f1) on update set null:
You have defined a SET NULL condition though some of the
columns are defined as NOT NULL.

Both error messages are not very useful, because the first does not really tell how the foreign key constraint is incorrectly formed and later does not say which column has the problem. This is improved in MariaDB 5.5.45 and 10.0.21:

create table t1 (f1 integer not null primary key) engine=innodb
--------------

Query OK, 0 rows affected (0.10 sec)

--------------
alter table t1 add constraint c1 foreign key (f1) references t1(f1) on update set null
--------------

ERROR 1005 (HY000): Can't create table 'test.#sql-2b40_2' (errno: 150)
--------------
show warnings
--------------

+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                                                                                                         |
+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning |  150 | Alter  table `test`.`t1` with foreign key constraint failed. You have defined a SET NULL condition but column f1 is defined as NOT NULL in  foreign key (f1) references t1(f1) on update set null close to  on update set null. |
| Error   | 1005 | Can't create table 'test.#sql-2b40_2' (errno: 150)                                                                                                                                                                              |
+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

Incorrect types

Column types for foreign key columns and referenced columns should match and use the same character set. If they do not, you currently get:

create table t1 (id int not null primary key, f1 int, f2 int, key(f1)) engine=innodb
--------------

Query OK, 0 rows affected (0.47 sec)

--------------
create table t2(a char(20), key(a), foreign key(a) references t1(f1)) engine=innodb
--------------

ERROR 1005 (HY000): Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
--------------
show warnings
--------------

+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                                         |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning |  150 | Create table 'test/t2' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
 |
| Error   | 1005 | Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")                                                                      |
| Warning | 1215 | Cannot add foreign key constraint                                                                                                                               |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
3 rows in set (0.00 sec)

--------+
show engine innodb status;
--------+
LATEST FOREIGN KEY ERROR
------------------------
2015-07-30 13:44:39 7f30e1520700 Error in foreign key constraint of table test/t2:
foreign key(a) references t1(f1)) engine=innodb:
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html
for correct foreign key definition.

But do we have an index for the referenced column f1 in the table t2? So if there are multiple columns in both the foreign key column list and the referenced column list, where do we look for the error? In MariaDB 5.5.45 and 10.0.21 this is improved by:

create table t1 (id int not null primary key, f1 int, f2 int, key(f1)) engine=innodb
--------------

Query OK, 0 rows affected (0.15 sec)

--------------
create table t2(a char(20), key(a), foreign key(a) references t1(f1)) engine=innodb
--------------

ERROR 1005 (HY000): Can't create table 'test.t2' (errno: 150)
--------------
show warnings
--------------

+---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                                                                            |
+---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning |  150 | Create  table `test`.`t2` with foreign key constraint failed. Field type or character set for column a does not mach referenced column f1 close to foreign key(a) references t1(f1)) engine=innodb |
| Error   | 1005 | Can't create table 'test.t2' (errno: 150)                                                                                                                                                          |
+---------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

Conclusions

There are several different ways to incorrectly define a foreign key constraint. In many cases when using earlier versions of MariaDB (and MySQL), the error messages produced by these cases were not very clear or helpful. In MariaDB 5.5.45 and 10.0.21 there are clearly improved error messages to help out the user. Naturally, there is always room for further improvements, so feedback is more than welcome!

References

  • https://mariadb.atlassian.net/browse/MDEV-6697
  • https://mariadb.atlassian.net/browse/MDEV-8524

I have the following tables:

// Base Scans
CREATE TABLE `basescans` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(100) NULL DEFAULT NULL,
    `status_id` INT(10) UNSIGNED NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    CONSTRAINT `status_id_fk` FOREIGN KEY (`status_id`) REFERENCES `statuses` (`id`) ON UPDATE CASCADE ON DELETE SET NULL
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=COMPACT
AUTO_INCREMENT=29

// Statuses
CREATE TABLE `statuses` (
    `id` INT(10) UNSIGNED NULL AUTO_INCREMENT,
    `name` VARCHAR(100) NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
AUTO_INCREMENT=4

Trying to save the first table fails when I put in that foreign key constraint. Can’t figure out why. Both of the columns referenced in the constraint have the same type, size, etc:

INT(10) UNSIGNED NULL

They only have a difference default value. One has a default value of NULL, the other is AUTO_INCREMENT. I didn’t think that made a difference for foreign key constraints but I could be wrong.

Both tables are InnoDB and UFT8. What am I missing here?

UPDATED: My specific error:

/* SQL Error (1452): Cannot add or update a child row: a foreign key constraint fails (`db`.<result 2 when explaining filename '#sql-31c2_22ac1e1'>, CONSTRAINT `status_id_fk` FOREIGN KEY (`status_id`) REFERENCES `statuses` (`id`) ON DELETE SET NULL ON UPDATE CASCADE) */

In MySQL, Enter a row in the child table without having row in the parent table

Example of insert row in Child table without having a row in Parent table MySQL

  1. Create the table Parent P1 and Child C1.
mysql> create table p1(id integer primary key, name varchar(100));
Query OK, 0 rows affected (0.09 sec)

mysql> create table c1(cid integer primary key, pid integer, foreign key (pid) references p1(id));
Query OK, 0 rows affected (0.09 sec)

2. Insert data in the Parent and child table and child table throw error due to not presence of data in the parents table.

mysql> insert into p1 values (1,'a');
Query OK, 1 row affected (0.03 sec)

mysql> insert into p1 values (2,'b');
Query OK, 1 row affected (0.01 sec)

mysql> insert into c1 values (2,5);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`c1`, CONSTRAINT `c1_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `p1` (`id`))

3. Disable the foreign key check and enable it.

mysql> SET FOREIGN_KEY_CHECKS = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into c1 values (3,5);
Query OK, 1 row affected (0.02 sec)

mysql> SET FOREIGN_KEY_CHECKS = 1;
Query OK, 0 rows affected (0.00 sec)

4. After enabling the foreign key check, the insert query throw error again.

mysql> insert into c1 values (4,5);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`c1`, CONSTRAINT `c1_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `p1` (`id`))

5. Verify the data in both P1 and C1 tables.

mysql> select * from c1;
+-----+------+
| cid | pid  |
+-----+------+
|   3 |    5 |
+-----+------+
1 row in set (0.00 sec)

mysql> select * from p1;
+----+------+
| id | name |
+----+------+
|  1 | a    |
|  2 | b    |
+----+------+
2 rows in set (0.00 sec)

Создал Java проэкт который работает с базой данных в MySql через JDBC. У меня есть такие таблицы:

CREATE TABLE `brand` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin

CREATE TABLE `category` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `discount` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin

CREATE TABLE `producttype` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin

CREATE TABLE `product` (
  `id` int NOT NULL AUTO_INCREMENT,
  `brandId` int NOT NULL,
  `categoryId` int NOT NULL,
  `productTypeId` int NOT NULL,
  `price` double(10,2) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `brandId_idx` (`brandId`),
  KEY `categoryId_idx` (`categoryId`),
  KEY `prodoctTypeId_idx` (`productTypeId`),
  CONSTRAINT `brandId` FOREIGN KEY (`brandId`) REFERENCES `brand` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `categoryId` FOREIGN KEY (`categoryId`) REFERENCES `category` (`id`),
  CONSTRAINT `productTypeId` FOREIGN KEY (`productTypeId`) REFERENCES `producttype` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin

Я создал консольное Java приложение для работы с БД через Jdbc. В таблицы Brand, Category и productType данные вставились через Java без проблем, но когда я пытаюсь вставить данные в таблицу Product, то выдает такую ошибку:

Cannot add or update a child row: a foreign key constraint fails (`internetshop`.`product`, CONSTRAINT `productTypeId` FOREIGN KEY (`productTypeId`) REFERENCES `producttype` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)

  • Группа:
    Администратор
  • Сообщений:
    8995
  • Регистрация:
    20.02.2010

04.03.2011 01:05

Для многих своих таблиц Magento старается поддерживать целостность (непротиворечивость) данных между таблицами, и для этих целей использует ограничения для значений внешних ключей.
Выглядит это примерно так:

ALTER TABLE `directory_country_region_name`
	ADD CONSTRAINT `FK_DIRECTORY_REGION_NAME_REGION` 
		FOREIGN KEY (`region_id`) 
		REFERENCES `directory_country_region` (`region_id`) 
		ON DELETE CASCADE 
		ON UPDATE CASCADE
;

Если вы обновляете данные напрямую через SQL, вы можете столкнуться с сообщением «Foreign key constraint fails».
Сообщение означает, что обновляя записи одной таблицы, вы разорвали созданную командой «ADD CONSTRAINT» связь между её значениями и значениями другой таблицы, и MySQL видит, что целостность данных нарушена.
Соответственно, MySQL откажется выполнить вашу операцию и сообщит об ошибке «Foreign key constraint fails».

Если вы сознательно временно нарушаете целостность данных, то временно отключите проверку внешних ключей командой:

SET FOREIGN_KEY_CHECKS=0;

После выполнения команд, нарушающих ссылочную целостность и команд, восстанавливающих ссылочную целостность, верните контроль ссылочной целостности обратной командой:

SET FOREIGN_KEY_CHECKS=1;

The MySQL ERROR 1452 happens when you try to execute a data manipulation query into a table that has one or more failing foreign key constraints.

The cause of this error is the values you’re trying to put into the table are not available in the referencing (parent) table.

Let’s see an example of this error with two MySQL tables.

Suppose you have a Cities table that contains the following data:

+----+------------+
| id | city_name  |
+----+------------+
|  1 | York       |
|  2 | Manchester |
|  3 | London     |
|  4 | Edinburgh  |
+----+------------+

Then, you create a Friends table to keep a record of people you know who lives in different cities.

You reference the id column of the Cities table as the FOREIGN KEY of the city_id column in the Friends table as follows:

CREATE TABLE `Friends` (
  `firstName` varchar(255) NOT NULL,
  `city_id` int unsigned NOT NULL,
  PRIMARY KEY (`firstName`),
  CONSTRAINT `friends_ibfk_1` 
    FOREIGN KEY (`city_id`) REFERENCES `Cities` (`id`)
)

In the code above, a CONSTRAINT named friends_ibfk_1 is created for the city_id column, referencing the id column in the Cities table.

This CONSTRAINT means that only values recoded in the id column can be inserted into the city_id column.

(To avoid confusion, I have omitted the id column from the Friends table. In real life, You may have an id column in both tables, but a FOREIGN KEY constraint will always refer to a different table.)

When I try to insert 5 as the value of the city_id column, I will trigger the error as shown below:

INSERT INTO `Friends` (`firstName`, `city_id`) VALUES ('John', 5);

The response from MySQL:

ERROR 1452 (23000): Cannot add or update a child row: 
a foreign key constraint fails 
(`test_db`.`friends`, CONSTRAINT `friends_ibfk_1` 
FOREIGN KEY (`city_id`) REFERENCES `cities` (`id`))

As you can see, the error above even describes which constraint you are failing from the table.

Based on the Cities table data above, I can only insert numbers between 1 to 4 for the city_id column to make a valid INSERT statement.

INSERT INTO `Friends` (`firstName`, `city_id`) VALUES ('John', 1);

-- Query OK, 1 row affected (0.00 sec)

The same error will happen when I try to update the Friends row with a city_id value that’s not available.

Take a look at the following example:

UPDATE `Friends` SET city_id = 5 WHERE `firstName` = 'John';

-- ERROR 1452 (23000): Cannot add or update a child row

There are two ways you can fix the ERROR 1452 in your MySQL database server:

  • You add the value into the referenced table
  • You disable the FOREIGN_KEY_CHECKS in your server

The first option is to add the value you need to the referenced table.

In the example above, I need to add the id value of 5 to the Cities table:

INSERT INTO `Cities` VALUES (5, 'Liverpool');

-- Cities table:
+----+------------+
| id | city_name  |
+----+------------+
|  1 | York       |
|  2 | Manchester |
|  3 | London     |
|  4 | Edinburgh  |
|  5 | Liverpool  |
+----+------------+

Now I can insert a new row in the Friends table with the city_id value of 5:

INSERT INTO `Friends` (`firstName`, `city_id`) VALUES ('Susan', 5);

-- Query OK, 1 row affected (0.00 sec)

Disabling the foreign key check

The second way you can fix the ERROR 1452 issue is to disable the FOREIGN_KEY_CHECKS variable in your MySQL server.

You can check whether the variable is active or not by running the following query:

SHOW GLOBAL VARIABLES LIKE 'FOREIGN_KEY_CHECKS';

-- +--------------------+-------+
-- | Variable_name      | Value |
-- +--------------------+-------+
-- | foreign_key_checks | ON    |
-- +--------------------+-------+

This variable causes MySQL to check any foreign key constraint added to your table(s) before inserting or updating.

You can disable the variable for the current session only or globally:

-- set for the current session:
SET FOREIGN_KEY_CHECKS=0;

-- set globally:
SET GLOBAL FOREIGN_KEY_CHECKS=0;

Now you can INSERT or UPDATE rows in your table without triggering a foreign key constraint fails:

INSERT INTO `Friends` (`firstName`, `city_id`) VALUES ('Natalia', 8);
-- Query OK, 1 row affected (0.01 sec)

UPDATE `Friends` SET city_id = 17 WHERE `firstName` = 'John';
-- Query OK, 1 row affected (0.00 sec)
-- Rows matched: 1  Changed: 1  Warnings: 0

After you’re done with the manipulation query, you can set the FOREIGN_KEY_CHECKS active again by setting its value to 1:

-- set for the current session:
SET FOREIGN_KEY_CHECKS=1;

-- set globally:
SET GLOBAL FOREIGN_KEY_CHECKS=1;

But please be warned that turning off your FOREIGN_KEY_CHECKS variable will cause the city_id column to reference a NULL column in the cities table.

It may cause problems when you need to perform a JOIN query later.

Now you’ve learned the cause of ERROR 1452 and how to resolve this issue in your MySQL database server. Great work! 👍

  • Ошибка при подтверждении аккаунта гугл после сброса
  • Ошибка при подписи заявления атрибутный сертификат не найден
  • Ошибка при подписи документа росреестр 0x800b010a
  • Ошибка при подписи документа не удалось подключиться к jinn 1c
  • Ошибка при подписи документа истек не наступил срок действия 0x800b0101