Терминология MySQL «ограничения» и «внешние ключи» разница? - PullRequest
44 голосов
/ 22 ноября 2008

Я смотрю на документы MySQL здесь и пытаюсь разобраться в различии между ИНОСТРАННЫМИ КЛЮЧАМИ и ОГРАНИЧЕНИЯМИ. Я думал, что FK был ограничением, но документы, кажется, говорят о них, как будто они разные вещи.

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

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

Так что предложение CONSTRAINT необязательно. Почему вы включаете это или не включаете? Если вы пропустите это, MySQL создает внешний ключ, но не ограничение? Или это больше похоже на «CONSTRAINT» - это не более чем имя для вашего FK, поэтому, если вы его не укажете, вы получите анонимный FK?

Любые разъяснения будут с благодарностью.

Спасибо

Этан

Ответы [ 6 ]

58 голосов
/ 22 ноября 2008

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

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

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

9 голосов
/ 22 ноября 2008

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

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

3 голосов
/ 15 декабря 2015

На данный момент наши DDL CREATE TABLE имеют этот формат - обратите внимание на синтаксис определения UNIQUE KEY и FOREIGN KEY, который мы использовали.

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 автоматически создает INDEX-ы с именами 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 с ограничениями (Ref: 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 все еще автоматически создает INDEX-ы с именами uk1_my_table и fk1_my_table, но имя объекта FK не является чем-то другим - это fk1_my_table, как упомянуто в DDL. Так что ALTER TABLE my_table DROP FOREIGN KEY fk1_my_table работает, но оставляет одноименный INDEX.

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

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

1 голос
/ 25 апреля 2011

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

1 голос
/ 22 ноября 2008

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

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

0 голосов
/ 12 июля 2010

Это, пожалуй, самый запутанный топик в MySQL.

Многие люди говорят, что, например, «PRIMARY KEY», «FOREIGN KEY» и «UNIQUE» - это на самом деле индексы! (Официальная документация MySQL включена здесь)

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

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

Пример:

... FOREIGN KEY index_name (col_name1, col_name2, ...)

Если FOREIGN KEY является индексом, то мы должны иметь возможность использовать index_name для его обработки. Однако мы не можем.

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

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

...