我意识到,如果我的所有值都是固定宽度的,建议使用CHAR。但是,那又怎样?为了安全起见,为什么不为所有文本字段选择VARCHAR呢?


当前回答

我会选择varchar,除非列存储固定的值,如美国州代码-这总是2个字符长,有效的美国州代码列表不经常改变:)。

在其他情况下,甚至像存储哈希密码(固定长度),我会选择varchar。

为什么——char类型的列总是用空格填充,这使得列my_column定义为char(5),值为'ABC'在比较中:

my_column = 'ABC' -- my_column stores 'ABC  ' value which is different then 'ABC'

假的。

这个特性可能会在开发过程中导致许多恼人的bug,并使测试更加困难。

其他回答

这是典型的空间与性能的权衡。

在MS SQL 2005中,Varchar(或每个字符需要两个字节的语言,如中文)是可变长度的。如果您在将行写入硬盘后再添加数据,则会将数据定位在与原始行不相邻的位置,并导致数据文件碎片化。这将影响性能。

所以,如果空间不是问题,那么Char格式的性能更好,但如果你想保持数据库的大小,那么varchars格式更好。

Char更快一点,所以如果你知道一个列有一定的长度,就使用Char。例如,存储(M)ale/(F)emale/(U)nknown表示性别,或者存储2个字符表示美国的一个州。

使用CHAR (NCHAR)和VARCHAR (NVARCHAR)会在数据库服务器存储数据的方式上带来不同。第一个引入了尾随空格;我在SQL SERVER函数中使用LIKE操作符时遇到了问题。因此,我必须始终使用VARCHAR (NVARCHAR)来确保它的安全性。

例如,如果我们有一个表TEST(ID INT, Status CHAR(1)),你写一个函数列出所有具有特定值的记录,如下所示:

CREATE FUNCTION List(@Status AS CHAR(1) = '')
RETURNS TABLE
AS
RETURN
SELECT * FROM TEST
WHERE Status LIKE '%' + @Status '%'

在这个函数中,我们期望当我们输入默认参数时,函数会返回所有的行,但实际上并没有。将@Status数据类型更改为VARCHAR将解决该问题。

我支持吉姆·麦基思的评论。

此外,如果您的表只有CHAR列,那么索引和全表扫描会更快。基本上,优化器将能够预测每条记录有多大,如果它只有CHAR列,而它需要检查每个VARCHAR列的大小值。

此外,如果您将VARCHAR列更新到比其先前内容更大的大小,则可能会强制数据库重新构建其索引(因为您强制数据库将记录物理地移动到磁盘上)。而对于CHAR列,这种情况永远不会发生。

但是,除非表很大,否则您可能不会关心性能受到的影响。

记住吉布拉的至理名言。早期的性能优化是万恶之源。

除了性能方面的好处外,CHAR还可以用来表示所有值都应该是相同的长度,例如,美国州缩写的列。