Разница в терминологии MySQL “ограничения” и “внешние ключи”?

StackOverflow https://stackoverflow.com/questions/310561

Вопрос

Я смотрю на документы MySQL здесь и пытаюсь разобраться в различии между ВНЕШНИМИ ключами и ограничениями.Я думал , что ФК был ограничение, но документы, похоже, говорят о них так, как будто это отдельные вещи.

Синтаксис для создания FK такой (частично)...

[CONSTRAINT [symbol]] FOREIGN KEY
    [index_name] (index_col_name, ...)
    REFERENCES tbl_name (index_col_name,...)

Таким образом, предложение "CONSTRAINT" является необязательным.Зачем вам включать это или не включать?Если вы оставите это в стороне, создает ли MySQL внешний ключ, но не ограничение?Или это больше похоже на то, что "ОГРАНИЧЕНИЕ" - это не что иное, как имя для вас FK, поэтому, если вы не укажете его, вы получите анонимный FK?

Мы были бы весьма признательны за любые разъяснения.

Спасибо,

Итан

Это было полезно?

Решение

Да, внешний ключ - это тип ограничения.MySQL имеет неравномерную поддержку ограничений:

  • PRIMARY KEY:да, как ограничение таблицы и ограничение столбца.
  • FOREIGN KEY:да, как ограничение таблицы, но только с механизмами хранения InnoDB и BDB;в противном случае анализируется, но игнорируется.
  • CHECK:анализируется, но игнорируется во всех системах хранения.
  • UNIQUE:да, как ограничение таблицы и ограничение столбца.
  • NOT NULL:да, как ограничение столбца.
  • DEFERRABLE и другие атрибуты ограничения:никакой поддержки.

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

Другие советы

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

Возвращаясь к конкретному вопросу, вы правы, опуская часть CONSTRAINT [symbol], вы создадите FK с автоматически сгенерированным именем.

На данный момент наши DDL-файлы CREATE TABLE имеют этот формат - обратите внимание на синтаксис определения УНИКАЛЬНОГО КЛЮЧА и ВНЕШНЕГО КЛЮЧА, который мы использовали.

CREATE TABLE my_dbschema.my_table (
    id INT unsigned auto_increment PRIMARY KEY,
    account_nbr INT NOT NULL,
    account_name VARCHAR(50) NOT NULL,
    active_flg CHAR(1) NOT NULL DEFAULT 'Y',
    vendor_nbr INT NOT NULL,
    create_ts TIMESTAMP NOT NULL DEFAULT current_timestamp,
    create_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR',
    last_upd_ts TIMESTAMP NOT NULL DEFAULT current_timestamp ON UPDATE current_timestamp,
    last_upd_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR',
    UNIQUE KEY uk1_my_table(account_nbr, account_name),
    FOREIGN KEY fk1_my_table(vendor_nbr) REFERENCES vendor(vendor_nbr)
    );

В этом формате MySQL автоматически создает индексы с именами uk1_my_table и fk1_my_table;но имя объекта FK - это нечто другое - my_table_ibfk_1 (т.Е.tablename_ibfk_N – определяется системой) .Итак ALTER TABLE my_table DROP FOREIGN KEY fk1_my_table не будет работать (и, следовательно, расстраивать и вызывать тревогу), так как нет объекта FK db с таким именем.

Вот альтернативный формат DDL для constarints (Ссылка : https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html) :-

CREATE TABLE my_dbschema.my_table (
    id INT unsigned auto_increment PRIMARY KEY,
    account_nbr INT NOT NULL,
    account_name VARCHAR(50) NOT NULL,
    active_flg CHAR(1) NOT NULL DEFAULT 'Y',
    vendor_nbr INT NOT NULL,
    create_ts TIMESTAMP NOT NULL DEFAULT current_timestamp,
    create_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR',
    last_upd_ts TIMESTAMP NOT NULL DEFAULT current_timestamp ON UPDATE current_timestamp,
    last_upd_usr_id VARCHAR(10) NOT NULL DEFAULT 'DFLTUSR',
    CONSTRAINT uk1_my_table UNIQUE KEY (account_nbr, account_name),
    CONSTRAINT fk1_my_table FOREIGN KEY (vendor_nbr) REFERENCES vendor(vendor_nbr)
    );

В этом формате MySQL по-прежнему автоматически создает индексы с именами uk1_my_table и fk1_my_table, но имя объекта FK не является чем–то другим - это fk1_my_table, как указано в DDL.Итак ALTER TABLE my_table DROP FOREIGN KEY fk1_my_table работает, но оставляет после себя одноименный ИНДЕКС.

И, обратите внимание, что ALTER TABLE my_table DROP INDEX fk1_my_table не будет работать изначально (когда FK еще не удален) с сообщением об ошибке, что он используется в FK!Если команда DROP FK была выполнена успешно, только тогда работает DROP INDEX.

Надеюсь, это объясняет и помогает устранить путаницу.

Не могу ответить за MySQL, но FK - это ограничения.Все, что приводит ваши данные в определенное состояние, является ограничением.Существует несколько видов ограничений: Уникальный, Первичный ключ, Проверка и Внешние ключи - все это ограничения.Возможно, у MySQL есть и другие.

Иногда в командах допускаются слова, но они не требуются полностью для удобства чтения, как, например, FROM в инструкции DELETE.

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

Это, вероятно, самый запутанный topìc в MySQL.

Многие люди говорят, что, например, "ПЕРВИЧНЫЙ КЛЮЧ", "ВНЕШНИЙ КЛЮЧ" и "УНИКАЛЬНЫЙ" ключ на самом деле являются индексами!(Официальная документация MySQL включена здесь)

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

Если они действительно являются индексами, то какой смысл использовать ограничение clausule для того, чтобы присвоить ему имя, поскольку предполагается, что вы можете использовать имя этого индекса при его создании?

Пример:

...Имя индекса ВНЕШНЕГО КЛЮЧА (col_name1, col_name2, ...)

Если ВНЕШНИЙ КЛЮЧ является индексом, то мы должны иметь возможность использовать index_name для его обработки.Однако мы не можем.

Но если это не индексы, а фактические ограничения, которые используют индексы для работы, тогда это имеет смысл.

В любом случае, мы не знаем.На самом деле, похоже, никто не знает.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top