Внешние ключи в MySQL? - PullRequest
       19

Внешние ключи в MySQL?

20 голосов
/ 25 октября 2008

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

Камень преткновения, с которым я столкнулся в этом, - это внешние ключи в MySQL. Я не могу найти ничего другого, кроме того, что они существуют в схеме хранения InnoDB , которую имеет MySQL.

Что представляет собой простой пример внешних ключей, реализованных в MySQL?

Вот часть схемы, которую я написал, которая, кажется, не работает, если вы скорее укажете на мой недостаток, чем покажете мне рабочий пример.

CREATE TABLE `posts` (
`pID` bigint(20) NOT NULL auto_increment,
`content` text NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`uID` bigint(20) NOT NULL,
`wikiptr` bigint(20) default NULL,
`cID` bigint(20) NOT NULL,
PRIMARY KEY  (`pID`),
Foreign Key(`cID`) references categories,
Foreign Key(`uID`) references users
) ENGINE=InnoDB;

Ответы [ 5 ]

21 голосов
/ 25 октября 2008

Если ваши категории и таблица пользователей уже существуют и содержат соответственно cID и uID в качестве первичных ключей, это должно работать:

CREATE TABLE `posts` (
`pID` bigint(20) NOT NULL auto_increment,
`content` text NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`uID` bigint(20) NOT NULL,
`wikiptr` bigint(20) default NULL,
`cID` bigint(20) NOT NULL,
PRIMARY KEY  (`pID`),
Foreign Key(`cID`) references categories(`cID`),
Foreign Key(`uID`) references users(`uID`)
) ENGINE=InnoDB;

Имя столбца требуется в предложении references.

9 голосов
/ 25 октября 2008

Отредактировано: Роберт и Винко заявляют, что вам нужно объявить имя столбца, на который есть ссылка, в ограничении внешнего ключа. Это необходимо в InnoDB, хотя в стандартном SQL вы можете не указывать имя столбца, на который ссылаются, если оно совпадает с именем в родительской таблице.

Одна особенность, с которой я столкнулся в MySQL, заключается в том, что объявление внешнего ключа молча завершится неудачей в нескольких случаях:

  • Ваша установка MySQL не включает движок innodb
  • Ваш конфигурационный файл MySQL не включает движок innodb
  • Вы не объявляете свою таблицу с модификатором таблицы ENGINE = InnoDB
  • Столбец внешнего ключа не совсем того же типа, что и столбец первичного ключа в ссылочной таблице

К сожалению, MySQL не выдает сообщения о том, что ему не удалось создать ограничение внешнего ключа. Он просто игнорирует запрос и создает таблицу без внешнего ключа (если вы показываете сообщения CREATE TABLE, вы можете не видеть объявления внешнего ключа). Я всегда думал, что это плохая особенность MySQL!

Совет: целочисленный аргумент для целочисленных типов данных (например, BIGINT (20)) не требуется. Это не имеет никакого отношения к размеру хранилища или диапазону столбца. BIGINT всегда имеет одинаковый размер независимо от аргумента, который вы ему даете. Число указывает, сколько цифр MySQL будет заполнять столбец, если вы используете модификатор столбца ZEROFILL.

4 голосов
/ 25 октября 2008

В этом есть некоторый код, показывающий, как создавать внешние ключи самостоятельно, и в CREATE TABLE.

Вот один из простых примеров из этого:

CREATE TABLE parent (
    id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE child (
    id INT, 
    parent_id INT,
    INDEX par_ind (parent_id),
    FOREIGN KEY (parent_id) REFERENCES parent(id)
    ON DELETE CASCADE
) ENGINE=INNODB;
3 голосов
/ 25 октября 2008

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

SHOW CREATE TABLE posts;
1 голос
/ 25 октября 2008

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

Всякий раз, когда вы делаете equijoin , вы приравниваете внешний ключ к чему-то, обычно к ключу, на который он ссылается. Пример:

select *
from 
   Students
inner join
   StudentCourses
on Students.StudentId = StudentCourses.StudentId

StudentCourses.StudentId - это внешний ключ, ссылающийся на Students.StudentId.

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