Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2318239
  • 博文数量: 473
  • 博客积分: 12252
  • 博客等级: 上将
  • 技术积分: 4307
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-12 10:02
文章分类

全部博文(473)

文章存档

2012年(8)

2011年(63)

2010年(73)

2009年(231)

2008年(98)

分类: Mysql/postgreSQL

2009-05-13 16:21:01


建表时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)

M个字节,0 <=M<= 255

(M)

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

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

Char为变长,varchartext为变长

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

引自:


阅读(1714) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~