Поиск

Как MySQL работает с ограничениями

MySQL позволяет работать как с транзакционными таблицами, для которых возмо­жен откат, так и с нетранзакционными, для которых откат не предусмотрен, поэтому работа с ограничениями (constraints) в MySQL несколько отличается от того, как это де­лается в других СУБД. Нам приходится иметь дело с ситуацией, когда нужно обновить множество строк в нетранзакционной таблице, причем нет возможности выполнить откат при возникнове­нии ошибки. Базовая философия состоит в том, чтобы попытаться сгенерировать ошибку для все­го, что можно обнаружить во время компиляции, но попытаться восстановиться после любой ошибки, возникшей во время выполнения. Мы достигаем этого в большинстве случаев, но пока еще не во всех (см. раздел Новые средства, запланированные на ближайшее будущее). Выбор, который стоит перед MySQL сводится к тому, что в случае возникновения ошибки необходимо остановить выполнение оператора на полпути или восстановить данные настолько хорошо, насколько возможно, и продолжать работу. В последующих разделах описано, что происходит в этих случаях с различными ти­пами ограничений.

Ограничение PRIMARY KEY/UNIQUE
Нормально, если генерируется ошибка при попытке вставить или обновить запись, которая приводит к нарушению ограничений первичного ключа, внешнего ключа или уникального ключа. Если используется транзакционный механизм хранения, подобный InnoDB, MySQL автоматически выполнит откат транзакции. Если же применяется не-транзакционный механизм хранения, MySQL остановится на некорректной записи и ос­тавит все оставшиеся записи неизмененными. Чтобы облегчить жизнь, MySQL поддерживает ключевое слово IGNORE для большин­ства команд, которые могут привести к нарушению ключей (например, INSERT IGNORE или UPDATE IGNORE). В этих случаях MySQL просто игнорирует любые нарушения огра­ничений ключей и продолжает обрабатывать остальные строки. Информация о том, что предпринял MySQL, доступна через функцию mysql_info() API-интерфейса С. В MySQL 4.1 и последующих версиях можно также воспользоваться командой SHOW WARNINGS. Стоит напомнить, что на данный момент внешние ключи поддерживают только таб­лицы InnoDB. Реализация внешних ключей для таблиц MylSAM запланирована в версии MySQL 5.1.
Ограничения NOT NULL и значения DEFAULT
Чтобы обеспечить простое управление нетранзакционными таблицами, все столбцы таблиц в MySQL имеют значения по умолчанию. Если вы вставляете ;неправильное; значение в столбец, такое как NULL в столбец, объявленный как NOT NULL, или же слишком большое значение в числовой столбец, MySQL установит его значение в ;лучшее из возможных; вместо того, чтобы выдавать ошибку:
  • Если вы попытаетесь сохранить в числовом столбце значение, выходящее за пре­делы допустимого диапазона, сервер MySQL вставит вместо него ноль, мини­мально возможное либо максимально возможное значение для этого столбца.
  • В строковом столбце сервер MySQL сохранит либо пустую строку, либо самую длинную, которая может поместиться в данный столбец.
  • Если вы попытаетесь вставить строку, начинающуюся не с цифры, в числовой столбец, MySQL запишет туда 0.
    1. Если попытаться вставить значение NULL в столбец, не допускающий значений NULL, MySQL вставит вместо этого 0 в числовой столбец и пустую строку - в символьный. (Однако такое поведение при вставке одиночных записей может быть изменено, если скомпилировать сервер MySQL с опцией компиляции -dont_use_default_fields.) Это заставит операторы INSERT генерировать ошибки, если только вы явно не зададите значения для всех столбцов, которые требуют значений NOT NULL.
    2. MySQL позволит сохранить некоторые неправильные значения даты в столбцы типа DATE и DATETIME (например '2000-02-31' или '2000-02-00'). Идея состоит в том, что проверка корректности дат не является обязанностью сервера SQL. Если MySQL может сохранять значение даты и извлекать точно такое значение, он со­ храняет его таким, как получил. Если дата абсолютно неправильная (за пределами возможностей сервера сохранить ее), то вместо нее сохраняется специальное значения

    Причина существования изложенных правил заключается в том, что мы не можем проверить эти условия до тех пор, пока не начнется выполнение запроса. Мы не можем выполнить откат изменений, если сталкиваемся с проблемой после того, как несколько строк уже обновлены, поскольку данный тип таблиц может не поддерживать транзак­ции. Выбор в пользу прерывания выполнения оператора представляется неудачным - в этом случае получается, что обновление выполнено наполовину, что приводит к наи­худшему сценарию. В этом случае предпочтительнее сделать ;лучшее из возможного; и затем продолжить, как будто ничего не произошло. Это означает, что не стоит полагаться на MySQL в смысле проверки корректности данных столбцов. Вместо этого приложение само должно заботиться о том, чтобы от­правлять серверу MySQL только правильные данные. В MySQL 5.0 мы планируем провести улучшения, выдавая предупреждения, когда происходит автоматическое преобразование столбцов, плюс опцию, позволяющую отка­тить оператор, который пытается выполнить запрещенное присваивание данных до тех пор, пока используются только транзакционные таблицы. <р5> Ограничения ENUM и SET

    В MySQL 4,x ЕШМ не является настоящим ограничением, а просто наиболее эффек­тивным способом определения столбцов, которые могут содержать значения только из заданного набора возможных значений. Если вы вставляете некорректное значение в столбец типа ENUM, оно устанавливается в зарезервированное перечислимое значение 0, которое отображается как пустая строка в строчном контексте. При попытке вставки некорректного значения в столбец типа SET это значение игно­рируется. Например, если столбец может содержать значения 'а', 'Ь' и 'с', попытка сохранить в столбце значения 'а,х,Ь,у' приведет к сохранению 'a,b'.