建表时IP字段设成了varchar,但是由于要对其建索引,以达到与其它表结合查询时提高效率的目的,打算将它改成char,修改后竟然没有成功。

最后发现原来要改就必须把该表中的所有varchar和text的字段一次性都改为char:

alter table ip_table modify ipddress char(16) default '',modify status char(10) default '',modify memo char(255) default '';

又试了下,如果原表中都是char,只要把其中一个字段改为varchar或者text,则其它所有char字段自动改为varchar

……

alter table ip_table modify memo text;

之后表中的情况:

ipddress varchar(16)

status varchar(10)

memo text

mysql也太扯了……

到网上找了找,找到这样一个解释:

在同一个表中不能混用CHAR   和VA   R   C   H   A   R。MySQL   根据情况甚至会将列从一种类型转换为另一种类型。这样做的原因如下:

■   行定长的表比行可变长的表容易处理(其理由请参阅2   .   3节“选择列的类型”)。

■   表行只在表中所有行为定长类型时是定长的。即使表中只有一列是可变长的,该表的

行也是可变长的。

■   因为在行可变长时定长行的性能优点完全失去。所以为了节省存储空间,在这种情况

下最好也将定长列转换为可变长列。

这表示,如果表中有VARCHAR   列,那么表中不可能同时有CHAR   列;MySQL   会自动

地将它们转换为VARCHAR   列。例如创建如下一个表:

CREATE   TABLE   my_table
(
c1   CHAR(10),
c2   VARCHAR(10)
)

如果使用DESCRIBE   my_table   查询,则其输出如下:

Feild     Type                 Null     Key     Default     Extra

c1           varchar(10)   yes                 null

c2           varchar(10)   yes                 null

请注意,VARCHAR   列的出现使MySQL   将c1   也转换成了VARCHAR   类型。如果试图用

A   LTER   TABLE   将c1   转换为C   H   A   R,将不起作用。将VARCHAR   列转换为CHAR   的惟一办

法是同时转换表中所有VARCHAR   列:

ALTER   TABLE   my_table   MODIFY   c1   CHAR(10),MODIFY   c2   CHAR(10)区别:

1.CHAR的长度是固定的,而VARCHAR2的长度是可以变化的, 比如,字符串“abc",对于CHAR

(20),表示你的字符将占20个字节(包括17个空字符),而同样的VARCHAR2

(20)则只占用3个字节的长度,20只是最大值,当你存储的字符小于20时,按实际长度存储。

2.CHAR的效率比VARCHAR2的效率稍高。

3.目前VARCHAR是VARCHAR2的同义词。工业标准的VARCHAR类型可以存储空字符串,但是oracle不这样做,尽管它保留以后这样做

的权利。自己开发了一个数据类型VARCHAR2,这个类型不是一个标准的VARCHAR,它将在数据库中varchar列可以存储空字符串的特性改为存

储NULL值。如果你想有向后兼容的能力,建议使用VARCHAR2而不是VARCHAR。

何时该用CHAR,何时该用varchar2?

CHAR与VARCHAR2是一对矛盾的统一体,两者是互补的关系.

VARCHAR2比CHAR节省空间,在效率上比CHAR会稍微差一些,即要想获得效率,就必须牺牲一定的空间,这也就是我们在数据库设计上常说的‘以空间换效率’。

VARCHAR2虽然比CHAR节省空间,但是如果一个VARCHAR2列经常被修改,而且每次被修改的数据的长度不同,这会引起‘行迁移’(Row

Migration)现象,而这造成多余的I/O,是数据库设计和调整中要尽力避免的,在这种情况下用CHAR代替VARCHAR2会更好一些。

引自:http://blog.chinaunix.net/u2/83571/showart_1343042.html

检索的存储:

他们的存储方式和数据的检索方式都不一样。

数据的检索效率是:char>varchar>text

空间占用方面,要具体情况具体分析了。M个字节,0 <=M<= 255

L+1个字节,其中L<=M且0 <=M<= 65535

L+2个字节,其中L< 216

Char为变长,varchar,text为变长

Char在保存的时候,后面(右边)会用空格填充到指定的长度,在检索的时候后面的空格会去掉,所以检索出来的数据需要再用什么trim之类的函数去处理。(与sql server可能有些不同)

Varchar在保存的时候,不进行填充。当值保存和检索时尾部的空格仍保留。

TEXT列不能有默认值,存储或检索过程中,不存在大小写转换.

当存储的字符超过他们定义的长度时候,如果不是在sql服务器的严格模式下,都会自动截取合适的字段存储,而不会出现错误。但是,如果是中文的话同样要报错误:)比如定义char(4),然后insert (‘c哈哈’).

注意一点的,Char,Varchar不像数值类型,有系统默认长度,所以必须在括号里定义长度,可以有默认值

text不可以写默认值,后面如果指定长度,不会报错误,但是这个长度是不起作用的,意思就是你插入数据的时候,超过你指定的长度还是可以正常插入(严格模式下没有测试 :))

存储计算:

在使用UTF8字符集的时候,手册上是这样描叙的:

·基本拉丁字母、数字和标点符号使用一个字节。

·大多数的欧洲和中东手写字母适合两个字节序列:扩展的拉丁字母(包括发音符号、长音符号、重音符号、低音符号和其它音符)、西里尔字母、希腊语、亚美尼亚语、希伯来语、阿拉伯语、叙利亚语和其它语言。

·韩语、中文和日本象形文字使用三个字节序列。

但是,经过我的测试,中文汉字使用2个字节序列。

使用的一般规则:

1.经常变化的字段用char

2.知道固定长度的用char

3.尽量用varchar

4.超过255字节的只能用varchar或者text

5.能用varchar的地方不用text