为什么文本列在MySQL中没有默认值?

问题描述 投票:156回答:8

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

mysql default-value
8个回答
79
投票

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

另请参阅MySQL Bugtracker中尝试将其修复为错误#19498:

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

就个人而言,我认为这是一个错误。搜索“BLOB / TEXT列不能有默认值”会在Google上返回大约2,940个结果。其中大多数是在尝试安装在一个系统上运行但不在其他系统上运行的数据库脚本时不兼容的报告。

我正在为我的一个客户端修改的webapp上遇到同样的问题,最初部署在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'");

26
投票

如果没有对mySQL引擎的深入了解,我会说这听起来像是一种节省内存的策略。我认为原因是docs的这一段背后:

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

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


14
投票

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

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 ;

9
投票

“在TEXT / BLOB列中支持DEFAULT”是一个feature request in the MySQL Bugtracker (Bug #21532)

我发现我不是唯一一个想在TEXT列中放置默认值的人。我认为在MySQL的更高版本中应支持此功能。

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


6
投票

我通常在Linux上运行网站,但我也在本地Windows机器上开发。我遇到过这个问题很多次,只是在遇到问题时修复了表格。我昨天安装了一个应用程序,以帮助某人,当然再次遇到问题。所以,我决定是时候弄清楚发生了什么 - 并找到了这个帖子。我真的不喜欢将服务器的sql_mode更改为早期模式(默认情况下)的想法,所以我提出了一个简单的(我认为)解决方案。

这个解决方案当然要求开发人员包装他们的表创建脚本以补偿在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');

就是这样。


4
投票

作为主要问题:

有谁知道为什么不允许这样做?

仍然没有回答,我做了一个快速搜索,发现一个相对较新的来自QQ开发人员在MySQL Bugs

[2017年3月17日15:11]StåleDeraas

由开发者发布:

这确实是一个有效的功能请求,乍一看,添加可能看起来微不足道。但TEXT / BLOBS值不直接存储在用于读取/更新表的记录缓冲区中。因此,为它们分配默认值会有点复杂。

这不是明确的答案,但至少是问题的起点。

与此同时,我只是围绕它进行编码,要么使列可以为空,要么从应用程序代码中为每个''明确指定一个(默认的insert)值...


1
投票

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

这解决了问题。


-8
投票

你究竟在做什么?这里的快速测试表明,文本列可以很高兴地具有默认值:

    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)
© www.soinside.com 2019 - 2024. All rights reserved.