Почему текстовый столбец не может иметь значение по умолчанию в MySQL?

185

Если вы попытаетесь создать столбец TEXT в таблице и задать для него значение по умолчанию в MySQL, вы получите сообщение об ошибке (по крайней мере, в Windows). Я не вижу никакой причины, почему текстовый столбец не должен иметь значение по умолчанию. В документации MySQL нет объяснений. Это кажется мне нелогичным (и несколько разочаровывающим, поскольку я хочу значение по умолчанию!). Кто-нибудь знает, почему это не разрешено?

Russ
источник
1
Можем ли мы увидеть запрос, который вы использовали?
Роберт
2
Вы уверены, что хотите столбец TEXT, а не VARCHAR? Столбцы TEXT предназначены для вещей, длина которых может превышать 255 байт.
scy
5
Это должен быть комментарий. Кроме того, да, он имеет в виду TEXT- эти столбцы не могут иметь значения по умолчанию. VARCHARжестяная банка.
Пекка
1
Если вы используете phpmyadmin для настройки своей базы данных, возможно, стоит изучить mysql gui tools / workbench ...;)
dmp
1
Да, мне нужно более 255 символов, к сожалению.
Расс

Ответы:

92

Windows MySQL v5 выдает ошибку, но Linux и другие версии вызывают только предупреждение. Это должно быть исправлено. WTF?

Также посмотрите на попытку исправить это как ошибку # 19498 в MySQL Bugtracker:

Брайс Несбитт от 4 апреля 2008 г. 16:36: в
MS Windows правило «no DEFAULT» - это ошибка, а на других платформах это часто предупреждение. Хотя это и не ошибка, это возможно, если вы напишите код на мягкой платформе, а затем запустите его на строгой платформе:

Лично я считаю это ошибкой. Поиск по запросу «столбец BLOB / TEXT не может иметь значения по умолчанию» возвращает примерно 2 940 результатов в Google. Большинство из них являются сообщениями о несовместимости при попытке установить сценарии БД, которые работали в одной системе, но не в других.

Сейчас я сталкиваюсь с той же проблемой в веб-приложении, которое я изменяю для одного из моих клиентов, изначально развернутого в Linux MySQL v5.0.83-log. Я использую Windows MySQL v5.1.41. Даже пытаясь использовать последнюю версию phpMyAdmin для извлечения базы данных, она не сообщает о значении по умолчанию для рассматриваемого текстового столбца. Тем не менее, когда я пытаюсь запустить вставку в Windows (которая отлично работает при развертывании Linux), я получаю сообщение об ошибке по умолчанию в столбце ABC. Я пытаюсь воссоздать таблицу локально с очевидным значением по умолчанию (на основе выбора уникальных значений для этого столбца) и в итоге получаю очень полезный столбец BLOB / TEXT, который не может иметь значение по умолчанию .

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


Как отключить строгий режим в MySQL 5 (Windows):

  • Отредактируйте /my.ini и найдите строку

    sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
  • Замени это

    sql_mode='MYSQL40'
  • Перезапустите службу MySQL (при условии, что это mysql5)

    net stop mysql5
    net start mysql5
    

Если у вас есть права root / admin, вы можете выполнить

mysql_query("SET @@global.sql_mode='MYSQL40'");
Ku Logix
источник
3
Если у вас есть root-доступ и вы используете phpMyAdmin, перейдите на главную страницу (щелкните логотип phpMyAdmin), перейдите на вкладку «Переменные», найдите переменную sql_mode и нажмите «Изменить».
Гэвин
1
Я на CentOS 5.8 и MySQL v 14.14 Distrib 5.1.71 выдает ошибку вместо предупреждения при попытке установить значение по умолчанию для поля TEXT. Просто хочу заметить, что это работает не на каждой платформе Linux.
Алекс
OS X по крайней мере, кажется, выдает ошибку в эти дни. В документации dev.mysql.com/doc/refman/5.7/en/blob.html говорится, что столбцы BLOB и TEXT не могут иметь значения DEFAULT. FWIW (но не почему)
rogerdpack
31

Без глубокого знания движка mySQL я бы сказал, что это звучит как стратегия экономии памяти. Я предполагаю, что причина этого параграфа в документах :

Каждое значение BLOB или TEXT представляется внутри отдельно выделенным объектом. Это отличается от всех других типов данных, для которых хранилище выделяется один раз на столбец при открытии таблицы.

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

Пекка
источник
5
-1: хранение данных, таких как названия городов, в столбце TEXT фактически занимает меньше общей памяти, чем сохранение тех же данных в столбце CHAR или VARCHAR.
Дэвид Кэри
5
@ Давид, руководство, которое я цитирую, касается не хранения, а поиска.
Пекка
1
Я не понимаю, как это приведет к ненормальному использованию памяти и снижению производительности. Очевидно, что когда пользователь определяет значение по умолчанию, он ожидает снижения производительности независимо от типа данных (особенно при массовых операциях). Однако, насколько я понимаю, вы заявляете, что для поля BLOB / TEXT это снижение производительности относительно высокое по сравнению с другими типами данных? И как это связано с тем, что BLOB / TEXT хранится внутри как отдельный объект? Это не имеет никакого смысла для меня.
причудливый
27
ИМХО это не стратегия экономии памяти. Это либо ошибка, либо люди, которые ее написали, безумны. И я думаю, что это последнее, так как они не могут это исправить по крайней мере 8 лет. Основные функциональные возможности, которые есть в любой другой базе данных.
причудливый
2
Неважно, это все равно должно быть вариантом для людей, которые хотят его использовать.
Юрчик
15

Вы можете получить тот же эффект, что и значение по умолчанию, используя триггер

create table my_text

(
   abc text
);

delimiter //
create trigger mytext_trigger before insert on my_text
for each row
begin
   if (NEW.abc is null ) then
      set NEW.abc = 'default text';
   end if;
end
//
delimiter ;
Тим Чайлд
источник
14

В качестве основного вопроса:

Кто-нибудь знает, почему это не разрешено?

до сих пор не ответил, я сделал быстрый поиск и нашел относительно новое дополнение от разработчика MySQL на MySQL Bugs :

[17 марта 2017 15:11] Ståle Deraas

Опубликовано разработчиком:

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

Это не определенный ответ, но, по крайней мере, отправная точка для вопроса « почему» .

А пока я просто напишу код и сделаю столбец обнуляемым или явно назначу (по умолчанию '') значение для каждого insertиз кода приложения ...

Мартен Коецье
источник
13

«Поддержка DEFAULT в столбцах TEXT / BLOB» - это запрос функции в MySQL Bugtracker (Ошибка № 21532) .

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

Это не может быть исправлено в версии 5.0 MySQL, потому что очевидно, что это приведет к несовместимости и потере данных, если кто-то попытается перенести базу данных туда-обратно между (текущими) базами данных, которые не поддерживают эту функцию, и любыми базами данных, которые поддерживают эта особенность.

Дэвид Кэри
источник
Мне кажется, вы должны иметь возможность изменить его между "" и NULL для столбца TEXT, который допускает нулевое значение. Это кажется невозможным.
phpguru
6

Обычно я запускаю сайты в Linux, но я также занимаюсь разработкой на локальной машине с Windows. Я сталкивался с этой проблемой много раз и просто исправлял таблицы, когда сталкивался с проблемами. Я вчера установил приложение, чтобы выручить кого-то, и, конечно, снова столкнулся с проблемой. Итак, я решил, что пришло время выяснить, что происходит - и нашел эту ветку. Мне действительно не нравится идея изменения sql_mode сервера в более ранний режим (по умолчанию), поэтому я пришел к простому (как мне кажется) решению.

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

// Store the current sql_mode
mysql_query("set @orig_mode = @@global.sql_mode");

// Set sql_mode to one that won't trigger errors...
mysql_query('set @@global.sql_mode = "MYSQL40"');

/**
 * Do table creations here...
 */

// Change it back to original sql_mode
mysql_query('set @@global.sql_mode = @orig_mode');

Вот и все.

Даррелловская оранжерея
источник
1
Это не решает вопрос о том, почему MySQL имеет такое поведение вообще, но спасибо за то, что поделились своим подходом, чтобы другие тоже могли извлечь выгоду. Добро пожаловать в стек переполнения!
GargantuChet
1
Да, я знаю ... Мне придется еще раз изучить режим STRICT, чтобы понять, имеет ли он смысл - поскольку MySQL выдает предупреждение на окнах Nix, но не работает на окнах Windows. Это указывает на то, что с реализацией что-то может быть не так, независимо от платформы. Вы заметите, что в документации MySQL есть это сообщение: «BLOB и TEXT столбцы не могут иметь значения DEFAULT». Логично, что кажется, что реализация в версиях до 5 была фактически нарушена на всех платформах.
Даррелл Гринхаус
3

Для Ubuntu 16.04:

Как отключить строгий режим в MySQL 5.7:

Редактировать файл /etc/mysql/mysql.conf.d/mysqld.cnf

Если нижняя строка существует в mysql.cnf

sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

Затем замените его

sql_mode='MYSQL40'

В противном случае

Просто добавьте строку ниже в mysqld.cnf

sql_mode='MYSQL40'

Это решило проблему.

Шив Буя
источник