Як змусити MySQL прийняти 0 як дійсне значення автоматичного збільшення


77

Коротше кажучи, у мене є файл 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в це поле?

Відповіді:


94

З відповіді, яку я отримав тут :

Ви можете використовувати:

SET [GLOBAL|SESSION] sql_mode='NO_AUTO_VALUE_ON_ZERO'

Що, як описано тут , заважатиме MySQL інтерпретувати INSERT / UPDATE ID 0 як наступний ідентифікатор послідовності. Така поведінка буде обмежена NULL.

Це те, що я вважав би досить поганою поведінкою програми. Вам доведеться бути дуже обережним, щоб він послідовно використовувався, особливо якщо ви вирішите впровадити реплікацію пізніше.


17
Одне потрібно бути обережним: sql_modeце список прапорів, розділених комами. Якщо ви це зробите sql_mode='NO_AUTO_VALUE_ON_ZERO', ви можете випадково відключити інші прапори
Кіп

Це рішення в основному працювало для мене, однак мій дамп також включав деякі місця, де він перекривав sql_modeсередину файлу sql, а потім скидався до змінної, для OLD_SQL_MODEякої було встановлено повернення до кінця сценарію. Це перевизначило мій NO_AUTO_VALUE_ON_ZEROв середині мого сценарію, роблячи це не працює. Моїм рішенням було створити нову змінну, яку INIT_OLD_SQL_MODEя звик скинути до кінця, і після того, як я встановив sql_modeзначення NO_AUTO_VALUE_ON_ZERO, я встановив нову змінну, OLD_SQL_MODEяку могли б скинути ті тимчасові заміни
Джошуа Фріке

27

Перевірте режим 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 DEV сторінки теми на цьому

Оновлення

Для MariaDB використовуйте команду, зазначену в цьому коментарі

SET sql_mode='NO_AUTO_VALUE_ON_ZERO'

Це не спрацювало на MariaDB, мені довелося використовувати це:SET sql_mode='NO_AUTO_VALUE_ON_ZERO'
hiddeneyes02

@ hiddeneyes02 Це повідомлення від 2010 року, дякую за зауваження, я оновлю відповідь :)
IG Pascual

Не вдалося: SELECT @@ [ГЛОБАЛЬНА | СЕСІЯ] .sql_mode; Працював: SELECT @@ SESSION.sql_mode; Працював: SELECT @@ GLOBAL.sql_mode;
azoundria

14

Якщо ви не хочете мати справу зі змінними 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
Очевидно, це не працює, якщо ви використовуєте ціле число без знака.
fnkr

7

Невдалий безпечний спосіб:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.