如果你试图在一个表上创建一个TEXT列,并在MySQL中给它一个默认值,你会得到一个错误(至少在Windows上)。我看不出为什么文本列不应该有默认值。MySQL文档中没有给出任何解释。这对我来说似乎不合逻辑(而且有点令人沮丧,因为我想要一个默认值!)。有人知道为什么这是不允许的吗?


当前回答

如果对mySQL引擎没有任何深入的了解,我会说这听起来像是一种节省内存的策略。我想原因就在这段文档里:

每个BLOB或TEXT值在内部由一个单独分配的对象表示。这与所有其他数据类型形成对比,这些数据类型在打开表时为每列分配一次存储。

预先填充这些列类型似乎会导致内存使用和性能损失。

其他回答

对于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'

这就解决了问题。

在2018-10-22发布的MySQL 8.0.13中增加了使用表达式作为默认值的支持,适用于TEXT, JSON, BLOB和GEOMETRY。

你仍然不能写:

create table foo(bar text default 'baz')

但是你现在可以这样写:

create table foo(bar text default ('baz'))

它们的作用是一样的。

通过使用触发器,可以获得与默认值相同的效果

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 ;

这是一个非常古老的问题,但似乎仍然没有得到正确的回答。而且,我的这个答案并不是对“为什么文本列不能有默认值”这个问题的实际答案,但由于它不可能在评论中写长文本,而且我的评论可以帮助某人防止错误,这里是一个单独的答案:

有人说,出现错误是因为操作系统- Windows-Linux;但这与操作系统没有直接关系。(但是,MySQL在不同操作系统的不同安装程序中的默认设置可能有所不同,我不确定。)

主要原因是sql_mode设置的标志STRICT_TRANS_TABLES。如果TEXT数据类型列的INSERT语句中没有指定值,并且sql_mode设置中存在标志,那么MySQL将报告一个错误;如果标志不存在,MySQL只报告一个警告并插入记录。

因此,为了防止这个错误,可以从MySQL的sql_mode设置中删除STRICT_TRANS_TABLES。(如果影响对数据库的其他操作,则需要将模式重置为之前的值。)

根据文档SQL模式在MySQL…

对于STRICT_TRANS_TABLES, MySQL将一个无效值转换为该列最接近的有效值,并插入调整后的值。如果缺少一个值,MySQL将插入列数据类型的隐式默认值。无论哪种情况,MySQL都会生成警告而不是错误,并继续处理语句。隐式默认值在第11.6节“数据类型默认值”中描述。

... 和数据类型默认值的文档…

不能为BLOB、TEXT、GEOMETRY和JSON数据类型分配默认值。

... TEXT列不能有默认值,但如果从sql_mode中删除STRICT_TRANS_TABLES,那么MySQL在INSERT语句中如果TEXT列没有指定值,则插入空字符串"。

如果对mySQL引擎没有任何深入的了解,我会说这听起来像是一种节省内存的策略。我想原因就在这段文档里:

每个BLOB或TEXT值在内部由一个单独分配的对象表示。这与所有其他数据类型形成对比,这些数据类型在打开表时为每列分配一次存储。

预先填充这些列类型似乎会导致内存使用和性能损失。