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

时间:2010-08-12 10:56:31

标签: mysql default-value

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

8 个答案:

答案 0 :(得分:80)

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

答案 1 :(得分:26)

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

中的这一段落后
  

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

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

答案 2 :(得分: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 ;

答案 3 :(得分:9)

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

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

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

答案 4 :(得分: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');

就是这样。

答案 5 :(得分:5)

作为主要问题:

  

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

仍未得到解答,我进行了快速搜索,并在MySQL Bugs找到了MySQL开发人员的一个相对较新的补充:

  

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

     

发布者发布:

     

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

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

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

答案 6 :(得分: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'

解决了这个问题。

答案 7 :(得分:-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)