为什么不能在MySQL中有一个默认值的文本列?

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

Windows MySQL v5引发错误,但Linux和其他版本只会引发警告。 这需要修复。 WTF?

另请参阅MySQL Bugtracker中的错误#19498,

Bryce Nesbitt于2008年4月4日下午4点36分:
在MS Windows上,“no DEFAULT”规则是一个错误,而在其他平台上,通常是一个警告。 虽然不是一个错误,但是如果你在一个宽大的平台上编写代码,然后在一个严格的平台上运行它,可能会被这个困扰:

我个人认为这是一个错误。 search“BLOB / TEXT列不能有默认值”会在Google上返回约2,940条结果。 他们中的大多数是在尝试安装在一个系统上工作而不是在其他系统上工作的DB脚本时的不兼容性的报告。

我现在正在为我的一个客户端修改的webapp上运行相同的问题,最初部署在Linux MySQL v5.0.83-log上。 我正在运行Windows MySQL v5.1.41。 即使尝试使用最新版本的phpMyAdmin来提取数据库,它也不报告有问题的文本列的默认值。 然而,当我尝试在Windows上运行插入(在Linux部署上工作正常)时,我收到ABC列上没有默认的错误。 我试着用明显的默认值(基于该列的唯一值的select)在本地重新创build表,并最终接收到非常有用的BLOB / TEXT列,不能有默认值

同样,不保持跨平台的基本兼容性是不可接受的,并且是一个错误。


如何在MySQL 5中禁用严格模式(Windows):

  • 编辑/my.ini并查找行

     sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" 
  • 用它replace

     sql_mode='MYSQL40' 
  • 重新启动MySQL服务(假设它是mysql5)

     net stop mysql5 net start mysql5 

如果你有root / admin权限,你可以执行

 mysql_query("SET @@global.sql_mode='MYSQL40'"); 

没有任何关于mySQL引擎的深刻知识,我会说这听起来像是一种节省内存的策略。 我从文档中假设原因在这个段落后面:

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

预填充这些列types似乎会导致内存使用情况和性能损失。

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

 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 ; 

“支持TEXT / BLOB列中的DEFAULT”是MySQL Bugtracker中的function请求(Bug#21532) 。

我看到我不是唯一一个想在TEXT列中放置默认值的人。 我认为这个特性应该在MySQL的更高版本中得到支持。

这在MySQL 5.0版本中是无法修复的,因为如果有人试图在不支持该function的(当前)数据库和支持该function的任何数据库之间来回传输数据库,会导致不兼容和数据丢失该function。

我通常在Linux上运行网站,但我也在本地Windows机器上开发。 我碰到这个问题很多次,只是在遇到问题时才修正表格。 我昨天安装了一个应用程序来帮助别人,当然还是遇到了问题。 所以,我决定是时候弄清楚发生了什么 – 并find了这个线索。 我真的不喜欢把服务器的sql_mode更改为更早的模式(默认),所以我想出了一个简单的(我认为)解决scheme。

这个解决scheme当然要求开发者打包他们的表创build脚本来弥补在Windows上运行的MySQL问题。 您将在转储文件中看到类似的概念。 一个重要的警告是,如果使用分区,这可能会造成问题。

 // 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'); 

就是这样。

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

然后用它replace

 sql_mode='MYSQL40' 

除此以外

只需在mysqld.cnf中添加以下行即可

 sql_mode='MYSQL40' 

这解决了问题。

你到底在干什么? 这里的一个快速testing表明,文本列可以非常高兴地具有默认值:

  mysql> create table test (a char(32) not null default 'this works', b char(32) not null); Query OK, 0 rows affected (0.03 sec) mysql> insert into test (b) values('hello'); Query OK, 1 row affected (0.01 sec) mysql> select * from test; +------------+-------+ | a | b | +------------+-------+ | this works | hello | +------------+-------+ 1 row in set (0.00 sec)