Невозможно добавить или обновить дочернюю строку: ограничение внешнего ключа не выполняется, пока существуют данные - PullRequest
0 голосов
/ 20 февраля 2019

Я пытаюсь добавить ограничения внешнего ключа, и это не удается:

mysql> alter table order_info add constraint FKlnh846un1oe6hnwkqf5ovtjwo
foreign key (orderId) references orders (orderId);

ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails 
(`storefront`.`#sql-1601_28`, CONSTRAINT `FKlnh846un1oe6hnwkqf5ovtjwo`
 FOREIGN KEY (`orderId`) REFERENCES `orders` (`orderId`))




mysql> show create table orders;
| orders | CREATE TABLE `orders` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `amount` float NOT NULL,
  `couponCode` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `createdAt` datetime DEFAULT NULL,
  `email` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `orderId` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `phone` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `status` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `updatedAt` datetime DEFAULT NULL,
  `address_id` int(11) DEFAULT NULL,
  `deleted` tinyint(1) NOT NULL DEFAULT '0',
  `pGateway` varchar(255) COLLATE utf8_unicode_ci DEFAULT 'PAYU',
  PRIMARY KEY (`id`),
  UNIQUE KEY `UK_9erxssgysqmn8axwyq4er6hen` (`orderId`),
  KEY `FKf5464gxwc32ongdvka2rtvw96` (`address_id`),
  KEY `email_status_index` (`email`,`status`),
  KEY `createdAt_index` (`createdAt`),
  KEY `status_index` (`status`),
  CONSTRAINT `FKf5464gxwc32ongdvka2rtvw96` FOREIGN KEY (`address_id`) REFERENCES `address` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2961655 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |




mysql> show create table order_info;
| order_info | CREATE TABLE `order_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `createdAt` datetime DEFAULT NULL,
  `orderId` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `packageId` int(11) NOT NULL,
  `updatedAt` datetime DEFAULT NULL,
  `amount` int(11) NOT NULL,
  `status` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `expiry` datetime DEFAULT NULL,
  `child_id` int(11) DEFAULT NULL,
  `parent_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1916085 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |



mysql> select count(*) from orders;
+----------+
| count(*) |
+----------+
|  2773095 |
+----------+
1 row in set (0.69 sec)

mysql> select count(*) from order_info;
+----------+
| count(*) |
+----------+
|  1914367 |
+----------+
1 row in set (0.61 sec)

mysql> select orderId from order_info where orderId not in (select orderId from orders);
Empty set (5.07 sec)

mysql> select count(*) from order_info where orderId is null;
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.63 sec)

Теперь в обеих таблицах есть данные.Не существует такого идентификатора заказа, которого нет в таблице заказов.Тип данных обоих столбцов одинаков.Так почему же это дает ошибку?Что именно нарушается?Хотя я могу установить проверки внешнего ключа как false и затем создать ключ, я хочу знать, почему это ограничение не выполняется.

РЕДАКТИРОВАТЬ: добавлен последний запрос, чтобы проверить, что столбец, который должен стать внешним ключом, делаетне имеет нулевых значений.

1 Ответ

0 голосов
/ 20 февраля 2019

Кажется, что запрос:

select orderId from order_info where orderId not in (select orderId from orders)

не лучший кандидат, чтобы знать ошибочные точки данных.NOT EXISTS лучше, как предполагает @ paul-spiegel.Вот результат запроса:

mysql> select count(*) from order_info oi where not exists 
( select null from orders o where o.orderId = oi.orderId);
+----------+
| count(*) |
+----------+
|        6 |
+----------+
1 row in set (31.27 sec)

В order_info было 6 строк, чей orderId не существовал в таблице orders.

Документация для NOT EXISTS: https://dev.mysql.com/doc/refman/5.7/en/exists-and-not-exists-subqueries.html

Относительно: ВЫБРАТЬ * ГДЕ НЕ СУЩЕСТВУЕТ

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...