Oracle удалить первичный ключ

Обновлено: 21.11.2024

У нас возникла проблема с автоматическим индексированием первичного ключа (ПК), который не удаляется при удалении ПК. При создании PK oracle автоматически добавляет уникальный индекс для хранения правила первичного ключа. Когда pk сбрасывается, индекс тоже сбрасывается. Это работает нормально, если оба оператора (create и drop) выполняются либо в Oracle 9, либо в Oracle 10, т. е. оба оператора выполняются в одной и той же версии.

Если база данных переносится из Oracle 9 в 10 между двумя операторами, индекс сохраняется.

Чтобы воспроизвести:
- Создайте первичный ключ в Oracle 9 и экспортируйте базу данных
- Импортируйте ее в Oracle 10
- Отбросьте первичный ключ

Результат:
Oracle 10 не удаляет уникальный индекс, созданный с помощью первичного ключа!

Пример SQL:
-- запустите это на oracle 9 --
тест CREATE TABLE ( pk INTEGER );
ИЗМЕНИТЬ ТАБЛИЦУ test ДОБАВИТЬ ОГРАНИЧЕНИЕ xpk_test PRIMARY KEY ( pk );

-- сделайте дамп с exp и импортируйте его в Oracle 10
-- запустите это в oracle 10 --
ALTER TABLE test DROP CONSTRAINT xpk_test;
-- теперь удаляется только первичный ключ xpk_test, индекс xpk_test остается

Почему?
Как избежать такого поведения? Есть ли специальный метод для работы со старыми (перенесенными) первичными ключами/индексами?

Буду признателен за любые подсказки!

Комментарии

Вместо ALTER TABLE test DROP CONSTRAINT xpk_test; вы можете отправить заявление ALTER TABLE test DROP CONSTRAINT xpk_test CASCADE; это сработает.

С уважением,
Камаль Шривастава

Изменить первичный ключ отбрасывания тестовой таблицы;

Надеюсь, это поможет

да оба утверждения, упомянутые выше
ALTER TABLE test DROP CONSTRAINT xpk_test CASCADE;
и
Alter table test отбрасывает первичный ключ;

удалить первичный ключ, но только ключ pk. :-(
Индекс сохраняется, когда эти операторы выполняются в базе данных, перенесенной с Oracle 9 на 10! Так что, к сожалению, нет никакой разницы с оператором, который мы использовали раньше.

следующий оператор делает то, что мы искали:

ALTER TABLE test DROP PRIMARY KEY DROP INDEX;

Удаляет PK и индекс и дает идентичные результаты для Oracle 9, Oracle 10 и баз данных, которые были перенесены с 9 на 10!

Спасибо за все подсказки,
Ф.

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

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

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

Посмотрите на приведенный ниже сценарий, здесь не используется экспорт-импорт, но в первом случае индекс не удаляется автоматически:

Все методы в порядке, я не знаю, есть ли у вас право удалить индекс. Я надеюсь, пока вы создали таблицу, используя уровень таблицы. Из oracle 9i у нас есть одна новая функция, создающая индекс при создании первичного ключа.
(Например) как
создать таблицу g1(a1 number(2) первичный ключ, используя index(создать индекс index_g1 на g1(a1))); затем, если вы будете следовать ранее упомянутой процедуре удаления, ваш индекс будет удален.

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

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

Поскольку вы выполнили экспорт и импорт, импорт работает,
создавая отдельный индекс, а затем добавляя отдельно
ограничение первичного ключа. Поскольку в случае
импорта эти две вещи происходят по отдельности, удаление
первичного ключа НЕ приведет к удалению индекса.
[. ]

Спасибо за подтверждение и объяснение такого поведения. Мы упустили из виду, что экспорт/импорт вызывает это изменение из-за отдельного воссоздания ранее существовавших pk и index. Тем не менее, у нас никогда не было таких проблем при переходе с оракула 8 на 9. Поэтому, несмотря на то, что это «ожидаемое поведение», оно выглядит как новое или измененное поведение. ;-)

Все методы хороши, я не знаю, есть ли у вас
привилегия удалить индекс. Я надеюсь, что вы
создали таблицу, используя уровень таблицы. Начиная с oracle 9i
у нас есть одна новая функция создания индекса при
создании первичного ключа.
(Например) как
создать таблицу g1(a1 number(2) первичный ключ, используя
index(создать индекс index_g1 на g1(a1))); затем, если вы
следуете ранее упомянутой процедуре удаления, ваш
индекс будет удален .

Да, не было бы проблем, если бы все ПК создавались при создании таблицы, то есть в одном операторе. Но в наших базах данных все PK создаются отдельными операторами ADD-CONSTRAINT после оператора CREATE-TABLE. В будущем мы можем использовать «подход с одним оператором». Но чтобы избежать проблем в будущем в уже перенесенных базах данных -- где связь между существующими PK и связанными индексами нарушена -- подход ". DROP PRIMARY KEY DROP INDEX" является единственным. работает.

Мне интересно, почему вам необходимо сбрасывать первичный ключ на стол при переходе с 9i на 10G?
Изменился ли список столбцов для первичного ключа или эта таблица больше не нуждается в первичном ключе?
что происходит с существующими запросами приложений, которые ранее полагались на этот индекс?

Мне интересно, зачем вам нужно сбрасывать
первичный ключ на стол при переходе с 9i на 10G?

О, это совпадение. Прямой связи между изменением ПК и миграцией нет. Просто не повезло: PK был изменен (то есть удален из одного столбца и воссоздан в другом столбце) в контексте редизайна таблицы во время дальнейшей разработки.

Долгая история: мы разрабатываем стандартное программное обеспечение, которое поддерживает различные базы данных, в том числе версии Oracle 9 и 10. Первоначальный ПК был создан много лет назад — еще до того, как появился оракул 9 ;-) — и теперь он был изменен во время крупного редизайна.

Поэтому мы были очень удивлены, обнаружив разницу в поведении между версиями 8/9 и 10. Когда вы создаете PK в версиях 8 или 9, делаете разные операции экспорта/импорта, а затем удаляете PK, индекс тоже исчезает. . Делая то же самое в Oracle 10, индекс сохраняется после одного экспорта/импорта даже без переноса.

Ну, это может быть новым ожидаемым поведением, если присмотреться к очевидно новому способу обработки этих ограничений во время экспорта/импорта. Но поскольку это не было поведением версий 8 и 9, на наш взгляд, это скорее неправильное поведение или, другими словами, ошибка, чем новая функция! :-(

Синтаксис column-definition для нового столбца является подмножеством синтаксиса для столбца в операторе CREATE TABLE.

Синтаксис DataType описан в разделе Типы данных. DataType может быть опущен, только если вы укажете предложение генерации. Если вы опустите DataType, тип сгенерированного столбца будет типом предложения генерации. Если вы укажете и DataType, и предложение-генерации, тип предложения-генерации должен назначаться DataType.

Подробнее о DefaultConstantExpression см. в разделе Столбец по умолчанию.

изменение столбца

В изменении столбца SET INCREMENT BY integer-constant указывает интервал между последовательными значениями столбца идентификаторов. Следующее значение, которое будет сгенерировано для столбца идентификаторов, будет определено из последнего присвоенного значения с примененным приращением. Столбец уже должен быть определен с атрибутом IDENTITY.

RESTART WITH integer-constant указывает следующее значение, которое будет сгенерировано для столбца идентификаторов. RESTART WITH полезен для таблицы, в которой есть столбец идентификаторов, определенный как GENERATED BY DEFAULT, и уникальный ключ, определенный для этого столбца идентификаторов. Поскольку GENERATED BY DEFAULT допускает как ручную вставку, так и значения, сгенерированные системой, возможно, что вставленные вручную значения могут конфликтовать со значениями, сгенерированными системой. Чтобы обойти такие конфликты, используйте синтаксис RESTART WITH, чтобы указать следующее значение, которое будет создано для столбца идентификаторов. Рассмотрим следующий пример, в котором используется комбинация автоматически сгенерированных данных и данных, вставленных вручную:

Система автоматически сгенерирует значения для столбца идентификации. Но теперь вам нужно вручную вставить некоторые данные в столбец идентификаторов:

На данный момент в столбце идентификаторов используются значения от 1 до 5. Если теперь вы хотите, чтобы система сгенерировала значение, система сгенерирует 3, что приведет к исключению уникального ключа, поскольку значение 3 уже было вставлено вручную. Чтобы компенсировать ручные вставки, выполните оператор ALTER TABLE для столбца идентификаторов с RESTART WITH 6:

ALTER TABLE не влияет на представления, ссылающиеся на изменяемую таблицу. Это включает в себя представления, которые имеют "*" в списке SELECT.Вы должны удалить и заново создать эти представления, если хотите, чтобы они возвращали новые столбцы.

Derby выдает ошибку, если вы пытаетесь изменить DataType сгенерированного столбца на тип, который нельзя назначить из типа предложения генерации. Derby также выдает ошибку, если вы пытаетесь добавить предложение DEFAULT в сгенерированный столбец.

Добавление столбцов

Синтаксис определения столбца для нового столбца почти такой же, как для столбца в операторе CREATE TABLE. Этот синтаксис позволяет поместить ограничение столбца в новый столбец в операторе ALTER TABLE ADD COLUMN. Однако столбец с ограничением NOT NULL можно добавить в существующую таблицу, если указать значение по умолчанию; в противном случае при выполнении инструкции ALTER TABLE выдается исключение.

Как и в CREATE TABLE, если определение столбца включает ограничение первичного ключа, столбец не может содержать значения NULL, поэтому необходимо также указать атрибут NOT NULL (SQLSTATE 42831).

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

Если вы добавите сгенерированный столбец в таблицу, Derby вычислит сгенерированные значения для всех существующих строк в таблице.

Добавление ограничений

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

ALTER TABLE ADD UNIQUE или PRIMARY KEY предоставляют сокращенный метод определения первичного ключа, состоящего из одного столбца. Если в определении столбца C указан PRIMARY KEY, эффект будет таким же, как если бы предложение PRIMARY KEY(C) было указано как отдельное предложение. Столбец не может содержать пустых значений, поэтому необходимо также указать атрибут NOT NULL.

Информацию о синтаксисе ограничений см. в разделе CONSTRAINT. Используйте синтаксис ограничения на уровне таблицы при добавлении ограничения с помощью синтаксиса ADD TABLE ADD CONSTRAINT.

Удаление столбцов

ALTER TABLE DROP COLUMN позволяет удалить столбец из таблицы.

Ключевое слово COLUMN указывать необязательно.

Ключевые слова CASCADE и RESTRICT также необязательны. Если вы не укажете ни CASCADE, ни RESTRICT, по умолчанию будет CASCADE.

Если вы укажете RESTRICT, удаление столбца будет отклонено, если это приведет к тому, что зависимый объект схемы станет недействительным.

Если вы укажете CASCADE, то при удалении столбца должны быть дополнительно удалены другие объекты схемы, которые стали недействительными.

Объекты схемы, которые могут привести к отклонению DROP COLUMN RESTRICT, включают: представления, триггеры, ограничения первичного ключа, ограничения внешнего ключа, ограничения уникального ключа, ограничения проверки и привилегии столбца. Если один из этих типов объектов зависит от удаляемого столбца, DROP COLUMN RESTRICT отклонит оператор.

Derby также вызывает ошибку, если указать RESTRICT при удалении столбца, на который ссылается предложение генерации сгенерированного столбца. Однако если вы укажете CASCADE, сгенерированный столбец также будет удален с семантикой CASCADE.

Вы не можете удалить последний (единственный) столбец в таблице.

CASCADE/RESTRICT не учитывает, используется ли удаляемый столбец в каких-либо индексах. Когда столбец удаляется, он удаляется из всех индексов, которые его содержат. Если этот столбец был единственным столбцом в индексе, весь индекс удаляется.

Удаление ограничений

ALTER TABLE DROP CONSTRAINT удаляет ограничение для существующей таблицы. Чтобы удалить безымянное ограничение, необходимо указать сгенерированное имя ограничения, хранящееся в SYS.SYSCONSTRAINTS, в качестве идентификатора с разделителями.

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

Изменение столбцов

    Увеличение ширины существующего столбца VARCHAR или VARCHAR FOR BIT DATA. CHARACTER VARYING или CHAR VARYING могут использоваться как синонимы для ключевого слова VARCHAR.

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

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

Чтобы задать интервал между последовательными значениями столбца идентификаторов, укажите целочисленную константу. Вы должны предварительно определить столбец с атрибутом IDENTITY (SQLSTATE 42837).Если в таблице есть существующие строки, значения в столбце, для которого было добавлено значение по умолчанию SET INCREMENT, не изменяются.

Вы можете добавить ограничение NOT NULL к существующему столбцу. Для этого не должно быть существующих значений NULL для столбца в таблице.

Вы можете удалить ограничение NOT NULL из существующего столбца. Для этого столбец не должен использоваться в ограничении PRIMARY KEY.

Вы можете использовать значение по умолчанию DEFAULT, чтобы изменить значение столбца по умолчанию. Чтобы отключить ранее установленное значение по умолчанию, используйте DROP DEFAULT (в качестве альтернативы вы можете указать NULL в качестве значения по умолчанию).

Настройка значений по умолчанию

Вы можете указать значение по умолчанию для нового столбца. Значение по умолчанию — это значение, которое вставляется в столбец, если не указано другое значение. Если это не указано явно, значением столбца по умолчанию является NULL. Если вы добавите значение по умолчанию в новый столбец, существующие строки в таблице получат значение по умолчанию в новом столбце.

Дополнительную информацию о значениях по умолчанию см. в инструкции CREATE TABLE.

Изменение степени детализации блокировки для таблицы

Предложение LOCKSIZE позволяет переопределить блокировку на уровне строк для конкретной таблицы, если в вашей системе используется настройка блокировки на уровне строк по умолчанию. (Если ваша система настроена на блокировку на уровне таблицы, вы не можете изменить степень детализации блокировки на блокировку на уровне строки, хотя Derby позволяет вам использовать предложение LOCKSIZE в такой ситуации без создания исключения.) Чтобы переопределить блокировку на уровне строки для конкретной таблицы, установите для таблицы блокировку TABLE. Если вы создали таблицу с детализацией блокировки на уровне таблицы, вы можете изменить блокировку обратно на ROW с помощью предложения LOCKSIZE в операторе ALTER TABLE STATEMENT. Информацию о том, почему это иногда полезно, см. в разделе Настройка базы данных Java.

Примеры

Результаты

Инструкция ALTER TABLE вызывает перекомпиляцию всех инструкций, зависящих от изменяемой таблицы, перед их следующим выполнением. ALTER TABLE не допускается, если есть открытые курсоры, ссылающиеся на изменяемую таблицу.

Вывод: в этом руководстве вы узнаете, как использовать ограничение Oracle PRIMARY KEY для управления первичным ключом таблицы.

Введение в первичный ключ

Первичный ключ – это столбец из комбинации столбцов в таблице, который однозначно идентифицирует строку в таблице.

Следующие правила делают столбец первичным ключом:

  • Столбец первичного ключа не может содержать значение NULL или пустую строку.
  • Значение первичного ключа должно быть уникальным во всей таблице.
  • Значение первичного ключа не должно меняться со временем.

В соответствии с этими правилами для первичных ключей даются следующие рекомендации:

  • Во-первых, первичный ключ не должен иметь смысла. Иногда вам может потребоваться использовать значимые данные, которые считаются уникальными, для первичных ключей, например, номер социального страхования (SSN), идентификационный номер автомобиля (VIN), адрес электронной почты и номер телефона. Однако вы не знаете, когда адрес электронной почты или номер телефона изменяется или повторно используется другим человеком. В таких случаях это создаст много проблем с данными. В мире баз данных искусственные ключи известны как суррогатные ключи, которые отличаются от естественных первичных ключей.
  • Во-вторых, первичные ключи должны быть компактными. Первичные ключи обычно являются числовыми, поскольку Oracle обычно обрабатывает числа быстрее, чем любые другие типы данных.

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

Чтобы создать первичный ключ в таблице, используйте ограничение PRIMARY KEY.

Примеры ограничений Oracle PRIMARY KEY

Обычно первичный ключ для таблицы создается при ее создании. Кроме того, вы можете добавить первичный ключ в таблицу постфактум, используя оператор ALTER TABLE.

Создание первичного ключа, состоящего из одного столбца

Следующий оператор CREATE TABLE создает таблицу Purchase_Orders:

Таблица Purchase_orders содержит четыре столбца: номер заказа на покупку (po_nr), идентификатор поставщика (vendor_id), статус заказа на покупку (po_status) и отметка времени ( created_at ), по которой был создан заказ на покупку.

В этой таблице столбец po_nr определен как первичный ключ с помощью предложения PRIMARY KEY.

Обратите внимание, что предложение PRIMARY KEY неявно делает столбец po_nr НЕ NULL, поэтому вам не нужно определять столбец следующим образом:

Ограничение PRIMARY KEY в этом примере является встроенным ограничением, поскольку оно находится в той же строке, что и столбец po_nr.

Рассмотрите следующее утверждение.

В этом примере в качестве ограничения таблицы использовалось ограничение PRIMARY KEY. Обратите внимание на следующее предложение:

Кроме того, мы явно присвоили ограничению PRIMARY KEY имя pk_purchase_orders .

Создание первичного ключа, состоящего из нескольких столбцов

Следующий оператор создает таблицу позиций заказа на покупку:

В этом примере первичный ключ таблицы Purchase_order_items состоит из двух столбцов: po_nr и item_nr . Это означает, что комбинация значений этих столбцов однозначно идентифицирует позицию заказа на покупку.

В этом примере не использовалось предложение CONSTRAINT для явного присвоения имени ограничению PRIMARY KEY. Поэтому Oracle неявно присвоила ограничению первичного ключа сгенерированное системой имя, например SYS_C0010617 .

Добавление первичного ключа в таблицу

Иногда может потребоваться добавить ограничение первичного ключа в существующую таблицу. Для этого вы используете оператор ALTER TABLE следующим образом:

В следующем примере сначала создается таблица vendors, а затем к ней добавляется ограничение первичного ключа:

Удаление ограничения Oracle PRIMARY KEY

Вы редко удаляете ограничение PRIMARY KEY из таблицы. Если вам необходимо это сделать, используйте следующий оператор ALTER TABLE.

Например, вы можете удалить ограничение первичного ключа таблицы поставщиков следующим образом:

Для удаления первичного ключа таблицы можно использовать следующий оператор:

Включить/отключить ограничение Oracle PRIMARY KEY

Чтобы повысить производительность при загрузке большого количества данных в таблицу или обновлении массива данных, вы можете временно отключить ограничение PRIMARY KEY.

Чтобы отключить ограничение PRIMARY KEY для таблицы, используйте оператор ALTER TABLE:

Например, чтобы отключить ограничение первичного ключа таблицы Purchase_orders, используйте следующую инструкцию:

Чтобы включить ограничение первичного ключа, используйте следующую инструкцию ALTER TABLE:

Следующий пример включает ограничение PRIMARY KEY таблицы Purchase_orders:

В этом руководстве вы узнали, как использовать ограничение Oracle PRIMARY KEY для создания, добавления, отключения, включения и удаления первичного ключа таблицы.

Справочное руководство по MySQL 5.6, включая Справочное руководство по MySQL NDB Cluster 7.3–7.4

13.1.17.5 Ограничения FOREIGN KEY

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

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

Основной синтаксис для определения ограничения внешнего ключа в операторе CREATE TABLE или ALTER TABLE включает следующее:

Использование ограничения внешнего ключа описано в следующих разделах этого раздела:

Идентификаторы

Именование ограничений внешнего ключа регулируется следующими правилами:

Значение символа CONSTRAINT используется, если оно определено.

Если предложение символ CONSTRAINT не определено или после ключевого слова CONSTRAINT не указан символ:

Для таблиц InnoDB имя ограничения создается автоматически.

Для таблиц NDB используется значение FOREIGN KEY имя_индекса, если оно определено. В противном случае имя ограничения создается автоматически.

Значение символа CONSTRAINT, если оно определено, должно быть уникальным в базе данных. Повторяющийся символ приводит к ошибке, похожей на следующую: ОШИБКА 1005 (HY000): не удается создать таблицу 'test.fk1' (номер ошибки: 121) .

Идентификаторы таблиц и столбцов во FOREIGN KEY . Предложение REFERENCES можно заключать в обратные кавычки ( ` ). В качестве альтернативы можно использовать двойные кавычки ( " ), если включен режим SQL ANSI_QUOTES. Также принимается во внимание параметр системной переменной lower_case_table_names.

Условия и ограничения

На ограничения внешнего ключа распространяются следующие условия и ограничения:

Родительская и дочерняя таблицы должны использовать один и тот же механизм хранения, и их нельзя определить как временные таблицы.

Для создания ограничения внешнего ключа требуется по крайней мере одна из привилегий SELECT , INSERT , UPDATE , DELETE или REFERENCES для родительской таблицы по версии 5.6.22.

Соответствующие столбцы во внешнем ключе и ссылочном ключе должны иметь одинаковые типы данных. Размер и знак типов с фиксированной точностью, таких как INTEGER и DECIMAL, должны быть одинаковыми . Длина строковых типов не обязательно должна быть одинаковой. Для столбцов недвоичных (символьных) строк набор символов и параметры сортировки должны быть одинаковыми.

MySQL поддерживает ссылки внешнего ключа между одним столбцом и другим в таблице. (Столбец не может иметь ссылку внешнего ключа на самого себя.) В этих случаях «запись дочерней таблицы» относится к зависимой записи в той же таблице.

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

InnoDB позволяет внешнему ключу ссылаться на любой индексный столбец или группу столбцов. Однако в ссылочной таблице должен быть индекс, в котором ссылочные столбцы являются первыми столбцами в том же порядке. Скрытые столбцы, которые InnoDB добавляет в индекс, также учитываются (см. Раздел 14.6.2.1, «Кластеризованные и вторичные индексы»).

NDB требует явного уникального ключа (или первичного ключа) для любого столбца, на который ссылается внешний ключ. InnoDB этого не делает, поскольку является расширением стандартного SQL.

Префиксы индексов для столбцов внешнего ключа не поддерживаются. Следовательно, столбцы BLOB и TEXT не могут быть включены во внешний ключ, поскольку индексы этих столбцов всегда должны включать длину префикса.

В настоящее время InnoDB не поддерживает внешние ключи для таблиц с пользовательским разделением. Сюда входят как родительские, так и дочерние таблицы.

Это ограничение не применяется к таблицам NDB, секционированным по KEY или LINEAR KEY (единственные типы пользовательского секционирования, поддерживаемые механизмом хранения NDB); они могут иметь ссылки на внешний ключ или быть целью таких ссылок.

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

Информацию о том, чем реализация MySQL ограничений внешнего ключа отличается от стандарта SQL, см. в Разделе 1.7.2.3, «Различия ограничений FOREIGN KEY».

Ссылочные действия

Когда операция UPDATE или DELETE влияет на значение ключа в родительской таблице, имеющей совпадающие строки в дочерней таблице, результат зависит от ссылочного действия, указанного в подпунктах ON UPDATE и ON DELETE инструкции ВНЕШНИЙ КЛЮЧ. Ссылочные действия включают:

КАСКАД: удалить или обновить строку из родительской таблицы и автоматически удалить или обновить соответствующие строки в дочерней таблице. Поддерживаются как ON DELETE CASCADE, так и ON UPDATE CASCADE. Между двумя таблицами не определяйте несколько предложений ON UPDATE CASCADE, которые воздействуют на один и тот же столбец в родительской таблице или в дочерней таблице.

Каскадные действия внешнего ключа не активируют триггеры.

SET NULL : удалить или обновить строку из родительской таблицы и установить для столбца или столбцов внешнего ключа в дочерней таблице значение NULL . Поддерживаются оба предложения ON DELETE SET NULL и ON UPDATE SET NULL.

Если вы укажете действие SET NULL, убедитесь, что вы не объявили столбцы в дочерней таблице как NOT NULL .

RESTRICT : отклоняет операцию удаления или обновления для родительской таблицы. Указание RESTRICT (или NO ACTION) равносильно пропуску предложения ON DELETE или ON UPDATE.

NO ACTION : ключевое слово из стандартного SQL. В MySQL эквивалентно RESTRICT. Сервер MySQL отклоняет операцию удаления или обновления для родительской таблицы, если в таблице, на которую ссылаются, есть связанное значение внешнего ключа. Некоторые системы баз данных имеют отложенные проверки, и NO ACTION является отложенной проверкой. В MySQL ограничения внешнего ключа проверяются немедленно, поэтому NO ACTION совпадает с RESTRICT .

SET DEFAULT : это действие распознается синтаксическим анализатором MySQL, но и InnoDB, и NDB отклоняют определения таблиц, содержащие предложения ON DELETE SET DEFAULT или ON UPDATE SET DEFAULT.

Для механизмов хранения, поддерживающих внешние ключи, MySQL отклоняет любую операцию INSERT или UPDATE, которая пытается создать значение внешнего ключа в дочерней таблице, если в родительской таблице нет соответствующего значения ключа-кандидата.

Для действий ON DELETE или ON UPDATE, которые не указаны, по умолчанию всегда используется действие RESTRICT .

Для таблиц NDB ON UPDATE CASCADE не поддерживается, если ссылка указывает на первичный ключ родительской таблицы.

InnoDB выполняет каскадные операции с использованием алгоритма поиска в глубину над записями индекса, соответствующего ограничению внешнего ключа.

Примеры ограничения внешнего ключа

Этот простой пример связывает родительскую и дочернюю таблицы с помощью внешнего ключа с одним столбцом:

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

Добавление ограничений внешнего ключа

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

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

Удаление ограничений внешнего ключа

Вы можете удалить ограничение внешнего ключа, используя следующий синтаксис ALTER TABLE:

Если в предложении FOREIGN KEY определено имя CONSTRAINT при создании ограничения, вы можете обратиться к этому имени, чтобы удалить ограничение внешнего ключа. В противном случае имя ограничения было сгенерировано внутри, и вы должны использовать это значение. Чтобы определить имя ограничения внешнего ключа, используйте SHOW CREATE TABLE :

Добавление и удаление внешнего ключа в одном и том же операторе ALTER TABLE поддерживается для ALTER TABLE . АЛГОРИТМ=НА МЕСТЕ . Он не поддерживается для ALTER TABLE . АЛГОРИТМ=КОПИРОВАНИЕ .

Проверка внешнего ключа

Переменная foreign_key_checks является динамической и поддерживает как глобальные, так и сеансовые области. Для получения информации об использовании системных переменных см. Раздел 5.1.8, «Использование системных переменных».

Отключение проверки внешнего ключа полезно, когда:

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

Перезагрузка таблиц в порядке, отличном от того, который требуется их отношениями внешнего ключа. Например, mysqldump создает правильные определения таблиц в файле дампа, включая ограничения внешнего ключа для дочерних таблиц. Чтобы упростить повторную загрузку файлов дампа для таблиц с отношениями внешнего ключа, mysqldump автоматически включает в вывод дампа оператор, отключающий Foreign_key_checks . Это позволяет импортировать таблицы в любом порядке на случай, если файл дампа содержит таблицы, не упорядоченные для внешних ключей. Отключение Foreign_key_checks также ускоряет операцию импорта, избегая проверки внешнего ключа.

Выполнение операций LOAD DATA, чтобы избежать проверки внешнего ключа.

Выполнение операции ALTER TABLE над таблицей, имеющей отношение внешнего ключа.

Если параметр foreign_key_checks отключен, ограничения внешнего ключа игнорируются, за следующими исключениями:

Повторное создание ранее удаленной таблицы возвращает ошибку, если определение таблицы не соответствует ограничениям внешнего ключа, которые ссылаются на таблицу. Таблица должна иметь правильные имена и типы столбцов. Он также должен иметь индексы на указанные ключи. Если эти требования не выполняются, MySQL возвращает ошибку 1005, которая ссылается на errno: 150 в сообщении об ошибке, что означает, что ограничение внешнего ключа было сформировано неправильно.

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

Удаление индекса, требуемого ограничением внешнего ключа. Перед удалением индекса необходимо снять ограничение внешнего ключа.

Создание ограничения внешнего ключа, когда столбец ссылается на несоответствующий тип столбца.

Отключение Foreign_key_checks имеет следующие дополнительные последствия:

Разрешается удалить базу данных, содержащую таблицы с внешними ключами, на которые ссылаются таблицы вне базы данных.

Разрешается удалить таблицу с внешними ключами, на которые ссылаются другие таблицы.

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

Определения внешних ключей и метаданные

Чтобы просмотреть определение внешнего ключа, используйте SHOW CREATE TABLE :

Ошибки внешнего ключа

В случае ошибки внешнего ключа, связанной с таблицами InnoDB (обычно это ошибка 150 на сервере MySQL), информацию о последней ошибке внешнего ключа можно получить, проверив выходные данные SHOW ENGINE INNODB STATUS.

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

Читайте также: