Работа с внешними ключами - не могу вставить - PullRequest
2 голосов
/ 28 марта 2010

Делаю мои первые попытки с внешними ключами в базе данных MySQL и пытаюсь выполнить вставку, которая завершается неудачей по этой причине: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails

Означает ли это, что внешние ключи ограничивают INSERTS, а также DELETES и / или UPDATES для каждой таблицы, для которой применяются отношения внешних ключей?

Спасибо!

Обновленное описание:

Products
----------------------------
id    | type
----------------------------
0     | 0
1     | 3

ProductsToCategories
----------------------------
productid | categoryid
----------------------------
0         | 0
1         | 1

Таблица продуктов имеет следующую структуру

CREATE  TABLE IF NOT EXISTS `alpha`.`products` (
  `id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `type` TINYINT(2) UNSIGNED NOT NULL DEFAULT 0 ,    
  PRIMARY KEY (`id`) ,  
  CONSTRAINT `funkyfunky`  
    FOREIGN KEY (`id` )
    REFERENCES `alpha`.`ProductsToCategories` (`productid` )    
    ON DELETE CASCADE,    
    ON UPDATE CASCADE)  

ENGINE = InnoDB;

Ответы [ 4 ]

4 голосов
/ 28 марта 2010

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

Предположим, у вас есть эти две таблицы:

Employees
----------------------------
EmpID | Name
----------------------------
0     | John
1     | Jane

OfficeAssignments
----------------------------
OfficeID | EmpID
----------------------------
0        | 0
1        | 1

Если у вас есть ограничение внешнего ключа на OfficeAssignments.EmpID -> Employees.EmpID, и вы пытаетесь выполнить:

INSERT INTO OfficeAssignments (OfficeID, EmpID) VALUES (2,2)

Оператор не выполнится, поскольку в таблице Employees нет записи с EmpID, равным 2.

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

Редактировать: Теперь, когда вы опубликовали ограничение, оно действительно выглядит так, как будто оно задано задом наперед. Помещая ограничение в определение таблицы Products, вы делаете ее дочерней, а ProductsToCategories родительской. Написанное вами ограничение можно прочесть как «Продукт должен быть присвоен категории, прежде чем он может быть создан». Я подозреваю, что вы имели в виду наоборот: «Продукт должен быть создан, прежде чем он может быть назначен категории». Чтобы получить такой результат, вам нужно поместить ограничение в таблицу ProductsToCategories, установив для внешнего ключа значение productid и сославшись на Products.id.

2 голосов
/ 28 марта 2010

Вы не можете удалить строку из родительской таблицы, пока на нее ссылается внешний ключ из дочерней таблицы. Также нельзя вставить / обновить в дочерней таблице недопустимые идентификаторы в столбце внешнего ключа.

Редактировать: «CONSTRAINT funkyfunky FOREIGN KEY (id)» должен быть объявлен в таблице «ProductsToCategories», а не в таблице «Products», потому что «ProductsToCategories» ссылается на «Products», а не наоборот, как вы.

1 голос
/ 28 марта 2010

Ваша таблица продуктов немного неверна, так как вам не нужно ничего ссылаться на нее Ссылки идут в «другие» таблицы и указывают на основную, например:

create table products (
  id int auto_increment,
  type int,
  primary key (id)
);

create table categories (
  id int auto_increment,
  name varchar(128),
  primary key (id)
)

create table products_to_categories (
  product_id int references products,
  category_id int references categories
);
1 голос
/ 28 марта 2010

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

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