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

Последние несколько недель я медленно изучал 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;

person icco    schedule 25.10.2008    source источник


Ответы (5)


Предполагая, что ваши категории и таблица пользователей уже существуют и содержат 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.

person Robert Gamble    schedule 25.10.2008

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

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

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

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

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

person Bill Karwin    schedule 25.10.2008
comment
Можете ли вы предоставить ссылку на свое утверждение относительно имен столбцов во внешнем ключе? Согласно синтаксису (dev.mysql. com / doc / refman / 5.0 / en /) это не необязательный параметр, и он не работает для меня, пока я не укажу его. - person Robert Gamble; 25.10.2008
comment
Да, вы правы, теперь, когда я проверяю это более внимательно, я наблюдаю то же самое. Стандартный SQL должен разрешать неявное имя столбца, на которое указывает ссылка, если оно совпадает с основной таблицей, но InnoDB, к сожалению, не поддерживает это. Моя вина! - person Bill Karwin; 25.10.2008
comment
Это зависит от вашей версии MySQL. В 5 не удается создать таблицу с полезным сообщением Ошибка 150, что означает не удалось создать таблицу или другую невероятно полезную вещь. - person MBCook; 25.10.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;
person DOK    schedule 25.10.2008
comment
Какое значение имеет строка INDEX par_ind (parent_id) ,? - person Nilanshu Jaiswal; 21.04.2021

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

SHOW CREATE TABLE posts;
person Vinko Vrsalovic    schedule 25.10.2008

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

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

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

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

person Walter Mitty    schedule 25.10.2008
comment
как вы думаете, вы могли бы еще немного объяснить, что это делает? Это просто соединение? - person icco; 26.10.2008