SQL数据类型VARCHAR(1)中是否有任何意义?

时间:2011-02-02 00:25:05

标签: sql sql-server-2005 types

我在最近不得不使用的数据库中碰到了很多VARCHAR(1)字段。我翻了个白眼:显然设计师没有任何线索。但也许我是那个需要学习的人。有没有可能的理由使用VARCHAR(1)数据类型而不是CHAR(1)?我认为RDMS会自动将一个转换为另一个。

数据库是MS SQL 2K5,但是在当天从Access发展而来。

3 个答案:

答案 0 :(得分:16)

是的,它有意义。

  • 更容易在语言中定义。定义varchar以允许1-8000比使用2+或3+到8000更为一致和容易。

  • VARCHAR(1)的VARying CHARacter方面就是这样。它可能不是最佳的存储,但传达了一个特定的含义,即数据是1个字符(课堂代码)或空白(外部活动)而不是NULL(未知/尚未分类)。

存储在这方面起着很小的作用 - 查看CHAR(1)的数据库模式,您几乎可以预期它必须始终具有1个char值,例如信用卡必须具有16个数字。对于某些数据而言,情况根本不是这样,它可以是一个数据,也可以不是一个数据。

对于那些说三态[1-char |]的人来说,使用VARCHAR(1)和CHAR(1)+ NULL组合也存在差异。 0-char | NULL]完全没用。它允许SQL语句,如:

select activity + '-' + classroom
from  ...

如果你使用char(1)+ NULL,否则会更加困难,这可以传达相同的信息,但有细微的差别。

答案 1 :(得分:10)

AFAIK,No。

a VARCHAR(1)需要3个字节的存储空间(存储空间大小是输入的实际数据长度+ 2个字节。Ref

CHAR(1)需要1个字节。

从存储角度来看:根据经验,如果它小于或等于5个字符,请考虑使用固定长度的char列。

避免使用varq(1)的原因(除了他们传达的设计推理很差,IMO)是在使用Linq2SQL时:LINQ to SQL and varchar(1) fields

答案 2 :(得分:5)

varchar(1)可以存储零长度(“空”)字符串。 char(1)不能,因为它会填充到单个空格。如果这种区别对您很重要,您可能会赞成varchar

除此之外,如果设计师想要允许将来可能需要更多字符的可能性,则可能有一个用例。

将固定长度数据类型从char(1)更改为char(2)意味着需要更新所有表行,并且首先删除访问此列的任何索引或约束。

对生产中的大表进行这些更改可能是一项非常耗时的操作,需要停机时间。

将列从varchar(1)更改为varchar(2)要容易得多,因为它只是一个元数据更改(引用该列的FK约束需要删除并重新创建,但不需要重建索引或更新数据页面)。

此外,每行节省2个字节可能并不总是实现。如果行定义已经很长,那么这并不总是会影响数据页面上可以容纳的行数。另一种情况是,如果在企业版中使用压缩功能,则存储数据的方式与Mitch在任何情况下的答案中提到的完全不同。 varchar(1)char(1)都会以相同的方式存储在短数据区域中。

@Thomas - 例如试试这个表定义。

CREATE TABLE T2
(
Code VARCHAR(1),
Foo datetime2,
Bar int,
Filler CHAR(4000),
PRIMARY KEY CLUSTERED (Code, Foo, Bar)
)

INSERT INTO T2
SELECT TOP 100000 'A', 
                  GETDATE(), 
                  ROW_NUMBER() OVER (ORDER BY (SELECT 0)),
                  NULL
FROM master..spt_values v1,  master..spt_values v2

CREATE NONCLUSTERED INDEX IX_T2_Foo ON T2(Foo) INCLUDE (Filler);
CREATE NONCLUSTERED INDEX IX_T2_Bar ON T2(Bar) INCLUDE (Filler);

对于varchar,将列定义从varchar(1)更改为varchar(2)是微不足道的。这是仅元数据的更改。

ALTER TABLE T2 ALTER COLUMN Code VARCHAR(2) NOT NULL

如果更改时间从char(1)char(2),则必须执行以下步骤。

  1. 从表中删除PK。这会将表转换为堆,并且意味着所有非聚簇索引都需要使用RID而不是聚簇索引键进行更新。
  2. 更改列定义。这意味着表格中的所有行都会更新,以便Code现在存储为char(2)
  3. 添加群集PK约束。除了重建CI本身,这意味着需要使用CI键作为行指针而不是RID再次更新所有非聚簇索引。