2010-08-12 117 views
129

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

+1

我们可以看到查询你用过的? – Robert 2010-08-12 10:59:54

+1

如果你正在使用phpmyadmin来设置你的数据库,可能想调查mysql的gui工具/工作台...;) – dmp 2010-08-12 11:05:00

+0

@pekka,我认为这只是一个很好的做法 - 而phpmyadmin是一个很棒的包,如果你真的想深入研究深入了解数据库的结构,并发现mysql能够实现的功能,那么一个像样的GUI软件包总是会有回报的。 Workbench与phpmyadmin确实有着不同的星球,但我意识到它并不总是一种选择。主要是 - 我发现使用mysql的初学者可以认为phpmyadmin是管理模式的“唯一”方式,从我自己的经验来看,第一次使用gui工具后,它就像隧道尽头的光。 – dmp 2010-08-12 18:51:13

回答

63

的Windows的MySQL V5抛出一个错误,但Linux和其它版本只提出一个警告。这需要修复。 WTF?

也看到试图在MySQL错误追踪系统来解决这个作为错误#19498:

布莱斯内斯比特于2008年4月4日下午4时36分:
在MS Windows中的“无DEFAULT”规则是错误,而在其他平台上,这往往是一个警告。虽然没有错误,但如果您在宽松的平台上编写代码,然后在严格的平台上运行代码,可能会受到此限制:

我个人认为这是一个错误。搜索“BLOB/TEXT列无法使用默认值”会在Google上返回约2,940条结果。其中大多数是在尝试安装在一个系统上工作但没有其他系统的DB脚本时出现不兼容的报告。

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

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


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

  • 编辑/我的。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 /管理员访问您可能能够执行

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

如果您有root权限并正在使用phpMyAdmin,请转到主页面(单击phpMyAdmin徽标),转到变量选项卡,找到sql_mode变量,然后单击编辑。 – Gavin 2014-01-12 20:27:12

+1

我在CentOS 5.8和MySQL v 14.14上试图将默认值设置为TEXT字段时,Distrib 5.1.71引发错误而不是警告。只是想注意到它不适用于每个Linux平台。 – Alex 2014-07-30 15:25:09

+0

OS X最近似乎在抛出一个错误。文档http://dev.mysql.com/doc/refman/5.7/en/blob.html说“BLOB和TEXT列不能有DEFAULT值。” FWIW(但不是为什么) – rogerdpack 2016-10-20 23:50:30

22

没有任何关于mySQL引擎的深入知识,我会说这听起来像是一种节省内存的策略。我假设原因在于docs

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

这似乎是预填充这些列类型会导致内存使用情况和性能处罚。

+3

-1:将数据(如城市名称)存储在TEXT列中实际所需的总内存少于存储CHAR或VARCHAR列中的相同数据。 – 2012-09-28 17:35:12

+4

@david我引用的手册章节不是关于存储,而是检索。 – 2012-09-28 20:22:31

+1

我不明白这会导致任何异常的内存使用情况和性能损失。很明显,当用户定义一个默认值时,无论数据类型是什么(特别是批量操作),他都希望性能达到要求。但据我所知,你认为对于BLOB/TEXT字段来说,与其他数据类型相比,这种性能命中率相对较高?这与BLOB/TEXT作为分离对象在内部存储的事实有什么关系?这对我来说没有任何意义。 – freakish 2014-05-21 12:24:38

-7

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

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) 
+2

啊 - 我不会阅读'文本列'的字面意思,是一个文本列.. – 2010-08-12 11:03:51

+4

对不起,你混淆了 - 我已经修改了问题,现在把文本放在大写,为清晰起见。 – Russ 2010-08-12 11:24:25

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

就是这样。

+0

这并没有解决为什么MySQL有行为的问题,但感谢分享你的方法,以便其他人也能受益。欢迎来到堆栈溢出! – GargantuChet 2012-09-17 04:37:08

+0

我知道......我必须进一步研究STRICT模式,看看它是否有意义 - 因为MySQL在Nix的盒子上发出警告,但在Windows盒子上失败。这表明无论平台如何,实施可能会出现问题。您会注意到,在MySQL的文档中,有这样的提示:“BLOB和TEXT列不能有DEFAULT值。”因此在逻辑上看来,在5之前的版本中的实现在所有平台上都被打破了。 – 2012-09-17 20:13:50

7

“支持TEXT/BLOB列中的默认值” 是 feature request in the MySQL Bugtracker (Bug #21532)

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

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

+0

在我看来,你应该能够在允许null的TEXT列的“”和NULL之间进行更改。这似乎不可能做到。 – phpguru 2017-08-14 23:41:48

8

您可以通过使用一个触发

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 ; 
0

对Ubuntu 16.04获得作为默认值相同的效果:

编辑文件/ etc:

如何在MySQL 5.7禁用严格模式/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' 

解决了这个问题。

0

由于主要问题:

有人知道为什么这是不允许的?

仍然没有回答,我做了快速搜索,发现从MySQL开发在MySQL Bugs一个相对较新:

[2017年3月17日15:11]陈旧Deraas

发布由开发人员:

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

这是没有确定的答案,但至少一个起点为什么问题。

在平均时间,我会围绕它只是代码,并可以使列可为空或明确指定每个insert从应用程序代码(默认'')值...