Как заставить MySQL принять 0 в качестве действительного значения автоинкремента - PullRequest
73 голосов
/ 17 июля 2009

Короче говоря, у меня есть файл SQL, который я хочу импортировать как файл стиля skel, так что это будет выполняться неоднократно, программно. Я могу редактировать файл SQL так, как захочу, но я бы предпочел не трогать само приложение.

Это приложение использует userid = 0 для представления анонимного пользователя. Он также имеет соответствующую (пустую) запись в базе данных для представления этого «пользователя». Следовательно, строка в моем skel.sql выглядит примерно так:

INSERT INTO `{{TABLE_PREFIX}}users` VALUES (0, '', '', '', 0, 0, 0, '', '', 0, 0, 0, 0, 0, NULL, '', '', '', NULL);

Проблема в том, что uid - это поле auto_increment, для которого технически 0 является недопустимым значением. Или, по крайней мере, если вы установите его в 0, вы в основном говорите MySQL: «Пожалуйста, введите следующий идентификатор в это поле».

Теперь, я полагаю, я мог бы поместить INSERT, а затем UPDATE запрос в мой файл SQL, но есть ли способ сказать MySQL в целом, что да, я действительно хочу вставить 0 в это поле?

Ответы [ 4 ]

88 голосов
/ 17 июля 2009

Из ответа я получил здесь :

Вы можете использовать:

SET [GLOBAL|SESSION] sql_mode='NO_AUTO_VALUE_ON_ZERO'

Что, как описано здесь , не позволит MySQL интерпретировать идентификатор INSERT / UPDATE, равный 0, как следующий идентификатор последовательности. Такое поведение будет ограничено значением NULL.

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

26 голосов
/ 09 сентября 2010

Проверьте режим sql DB с помощью:

SELECT @@[GLOBAL|SESSION].sql_mode;

Если оно пустое или не установлено, используйте:

SET [GLOBAL|SESSION] sql_mode='NO_AUTO_VALUE_ON_ZERO'

БУДЬТЕ ОСТОРОЖНЫ! Если вы используете GLOBAL, это не является немедленным изменением, вам необходимо перезапустить соединение, чтобы применить настройку.

Итак, если вы восстанавливаете данные, например, из одной БД в другую и не уверены, что этот параметр применяется, используйте SESSION для немедленного изменения (оно сбрасывается при закрытие соединения). Когда закончите, введите значение 0, и оно не изменится, даже если изменить sql_mode.

Для сброса этого режима (и других) используйте

SET [GLOBAL|SESSION] sql_mode=''

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

Для получения дополнительной информации проверьте Тема страницы разработчика MySQL на этом

Обновление

Для MariaDB используйте команду, указанную в этом комментарии

SET sql_mode='NO_AUTO_VALUE_ON_ZERO'
11 голосов
/ 01 июля 2015

Если вы не хотите иметь дело с переменными mysql, вот вам полезный хак:

INSERT INTO `{{TABLE_PREFIX}}users` VALUES (-1, '', '', '', 0, 0, 0, '', '', 0, 0, 0, 0, 0, NULL, '', '', '', NULL);

А потом

UPDATE `{{TABLE_PREFIX}}users` SET id = 0 where id = -1;

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

6 голосов
/ 08 декабря 2014

Отказоустойчивый способ:

SET @@session.sql_mode = 
    CASE WHEN @@session.sql_mode NOT LIKE '%NO_AUTO_VALUE_ON_ZERO%' 
        THEN CASE WHEN LENGTH(@@session.sql_mode)>0
            THEN CONCAT_WS(',',@@session.sql_mode,'NO_AUTO_VALUE_ON_ZERO')  -- added, wasn't empty
            ELSE 'NO_AUTO_VALUE_ON_ZERO'                                    -- replaced, was empty
        END
        ELSE @@session.sql_mode                                             -- unchanged, already had NO_AUTO_VALUE_ON_ZERO set
    END
  • Проверяет, установлен ли NO_AUTO_VALUE_ON_ZERO в sql_mode
  • Добавляет в sql_mode, если не пусто
  • Устанавливает только сеанс, я рекомендую использовать его только в сеансах, где нужно вставить 0
...