外观
SQLServer 数据类型支持
数据类型分类
SQLServer 支持多种数据类型,主要分为以下几类:
- 精确数值类型
- 近似数值类型
- 日期和时间类型
- 字符串类型
- 二进制类型
- 空间类型
- 层次结构类型
- JSON 和 XML 类型
- 特殊数据类型
精确数值类型
整数类型
| 数据类型 | 存储大小 | 范围 | 应用场景 |
|---|---|---|---|
| tinyint | 1 字节 | 0 到 255 | 小范围整数,如状态码、标志位 |
| smallint | 2 字节 | -32,768 到 32,767 | 中等范围整数,如数量、ID |
| int | 4 字节 | -2,147,483,648 到 2,147,483,647 | 常用整数类型,如主键、外键 |
| bigint | 8 字节 | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 | 大范围整数,如大数据量的主键 |
小数类型
| 数据类型 | 存储大小 | 范围 | 应用场景 |
|---|---|---|---|
| decimal(p,s) | 5-17 字节 | 取决于精度 | 精确小数,如货币、财务数据 |
| numeric(p,s) | 5-17 字节 | 取决于精度 | 同 decimal |
| smallmoney | 4 字节 | -214,748.3648 到 214,748.3647 | 小范围货币数据 |
| money | 8 字节 | -922,337,203,685,477.5808 到 922,337,203,685,477.5807 | 大范围货币数据 |
近似数值类型
| 数据类型 | 存储大小 | 范围 | 应用场景 |
|---|---|---|---|
| float(n) | 4 或 8 字节 | 取决于 n | 科学计算、统计分析 |
| real | 4 字节 | -3.40E+38 到 3.40E+38 | 科学计算、图形处理 |
日期和时间类型
基本日期时间类型
| 数据类型 | 存储大小 | 范围 | 精度 | 应用场景 |
|---|---|---|---|---|
| date | 3 字节 | 0001-01-01 到 9999-12-31 | 天 | 仅日期,如生日、订单日期 |
| time | 3-5 字节 | 00:00:00.0000000 到 23:59:59.9999999 | 100 纳秒 | 仅时间,如会议时间、操作时间 |
| datetime | 8 字节 | 1753-01-01 到 9999-12-31 | 0.00333 秒 | 传统日期时间,兼容性场景 |
| smalldatetime | 4 字节 | 1900-01-01 到 2079-06-06 | 1 分钟 | 低精度日期时间,如历史数据 |
增强日期时间类型
| 数据类型 | 存储大小 | 范围 | 精度 | 应用场景 |
|---|---|---|---|---|
| datetime2(n) | 6-8 字节 | 0001-01-01 到 9999-12-31 | 100 纳秒 | 高精度日期时间,推荐使用 |
| datetimeoffset(n) | 8-10 字节 | 0001-01-01 到 9999-12-31 | 100 纳秒 | 带时区的日期时间,跨国应用 |
字符串类型
固定长度字符串
| 数据类型 | 存储大小 | 范围 | 应用场景 |
|---|---|---|---|
| char(n) | n 字节 | 1 到 8,000 字节 | 固定长度字符串,如身份证号、手机号 |
可变长度字符串
| 数据类型 | 存储大小 | 范围 | 应用场景 |
|---|---|---|---|
| varchar(n) | 实际长度 + 2 字节 | 1 到 8,000 字节 | 可变长度字符串,如姓名、地址 |
| varchar(max) | 实际长度 + 2 字节 | 1 到 2^31-1 字节 | 大文本数据,如文章内容、备注 |
Unicode 字符串
| 数据类型 | 存储大小 | 范围 | 应用场景 |
|---|---|---|---|
| nchar(n) | 2n 字节 | 1 到 4,000 字节 | 固定长度 Unicode 字符串,如中文姓名 |
| nvarchar(n) | 实际长度 * 2 + 2 字节 | 1 到 4,000 字节 | 可变长度 Unicode 字符串,如中文描述 |
| nvarchar(max) | 实际长度 * 2 + 2 字节 | 1 到 2^30-1 字节 | 大 Unicode 文本,如中文文章、XML 内容 |
其他字符串类型
| 数据类型 | 存储大小 | 范围 | 应用场景 |
|---|---|---|---|
| text | 实际长度 + 2 字节 | 1 到 2^31-1 字节 | 传统大文本,已被 varchar(max) 替代 |
| ntext | 实际长度 * 2 + 2 字节 | 1 到 2^30-1 字节 | 传统大 Unicode 文本,已被 nvarchar(max) 替代 |
| xml | 实际长度 + 2 字节 | 1 到 2^31-1 字节 | XML 数据存储和查询 |
| json | 存储为字符串类型 | 取决于字符串类型 | JSON 数据存储和查询 |
二进制类型
| 数据类型 | 存储大小 | 范围 | 应用场景 |
|---|---|---|---|
| binary(n) | n 字节 | 1 到 8,000 字节 | 固定长度二进制数据,如哈希值 |
| varbinary(n) | 实际长度 + 2 字节 | 1 到 8,000 字节 | 可变长度二进制数据,如图片缩略图 |
| varbinary(max) | 实际长度 + 2 字节 | 1 到 2^31-1 字节 | 大二进制数据,如图片、文件 |
| image | 实际长度 + 2 字节 | 1 到 2^31-1 字节 | 传统大二进制数据,已被 varbinary(max) 替代 |
特殊数据类型
| 数据类型 | 存储大小 | 范围 | 应用场景 |
|---|---|---|---|
| bit | 1 位(8 位为 1 字节) | 0, 1, 或 NULL | 布尔值,如是否激活、是否删除 |
| uniqueidentifier | 16 字节 | 全局唯一标识符 | GUID、UUID,如分布式系统主键 |
| sql_variant | 实际数据大小 + 描述符 | 可以存储多种数据类型 | 灵活数据存储,如配置项 |
| table | 取决于数据 | 内存中临时表 | 存储结果集,如存储过程返回表 |
| cursor | 可变 | 游标引用 | 逐行处理数据,如存储过程中的游标 |
| timestamp | 8 字节 | 自动生成的二进制数 | 行版本控制,已被 rowversion 替代 |
| rowversion | 8 字节 | 自动生成的二进制数 | 行版本控制,乐观并发控制 |
空间数据类型
| 数据类型 | 描述 | 应用场景 |
|---|---|---|
| geometry | 平面空间数据 | 地图数据、地理位置 |
| geography | 圆形地球空间数据 | GPS 坐标、地理位置服务 |
层次结构数据类型
| 数据类型 | 描述 | 应用场景 |
|---|---|---|
| hierarchyid | 层次结构树的节点位置 | 组织架构、分类树、菜单结构 |
数据类型选择最佳实践
基本原则
- 选择最小的数据类型:根据实际数据范围选择最小的合适数据类型,减少存储空间和提高查询性能
- 优先使用精确数值类型:对于财务数据、数量等,优先使用 decimal 或 numeric 类型
- 使用适当的字符串类型:
- 固定长度数据使用 char 或 nchar
- 可变长度数据使用 varchar 或 nvarchar
- 大文本使用 varchar(max) 或 nvarchar(max)
- 根据国际化需求选择字符串类型:
- 仅英文数据使用非 Unicode 类型(char/varchar)
- 包含中文等非英文数据使用 Unicode 类型(nchar/nvarchar)
- 优先使用增强日期时间类型:
- 一般场景使用 datetime2
- 跨国应用使用 datetimeoffset
常见场景数据类型选择
主键选择
- 自增主键:使用 int 或 bigint(根据数据量大小)
- 分布式系统:使用 uniqueidentifier
- 层次结构:使用 hierarchyid
时间数据选择
- 仅存储日期:使用 date
- 仅存储时间:使用 time
- 同时存储日期和时间:使用 datetime2
- 带时区的时间:使用 datetimeoffset
文本数据选择
- 短文本(< 8000 字符):使用 varchar 或 nvarchar
- 长文本(> 8000 字符):使用 varchar(max) 或 nvarchar(max)
- XML 数据:使用 xml 类型
- JSON 数据:存储为 nvarchar(max),使用 JSON 函数处理
版本差异
SQLServer 2016 及以上
- 增强的 JSON 支持
- 新的日期时间函数
- 改进的空间数据类型
SQLServer 2019 及以上
- 增强的 UTF-8 支持
- 新的数据类型函数
Azure SQL Database
- 与 SQLServer 2019+ 兼容
- 支持所有现代数据类型
常见问题 (FAQ)
Q: char 和 varchar 有什么区别?
A: char 是固定长度字符串,即使存储的实际数据长度小于定义的长度,也会占用全部空间;varchar 是可变长度字符串,只占用实际数据长度加 2 字节的空间。
Q: nchar 和 char 有什么区别?
A: nchar 是 Unicode 字符串类型,每个字符占用 2 字节,支持所有语言字符;char 是非 Unicode 字符串类型,每个字符占用 1 字节,主要支持英文和西欧字符。
Q: datetime 和 datetime2 有什么区别?
A: datetime2 是 datetime 的增强版本,具有更大的日期范围、更高的精度和更小的存储大小。建议优先使用 datetime2。
Q: 什么时候应该使用 varbinary(max) 而不是 image?
A: image 是传统的数据类型,已被 varbinary(max) 替代。varbinary(max) 支持更多的 T-SQL 函数,并且在性能上更好,建议优先使用。
Q: 如何存储 JSON 数据?
A: SQLServer 没有专门的 JSON 数据类型,但可以使用 nvarchar(max) 存储 JSON 数据,并使用内置的 JSON 函数进行查询和处理。
Q: 如何选择主键的数据类型?
A: 根据具体场景选择:
- 自增主键:int 或 bigint(根据数据量)
- 分布式系统:uniqueidentifier
- 自然主键:根据业务数据类型选择
Q: 什么时候应该使用 sql_variant 类型?
A: sql_variant 类型允许存储多种数据类型的值,但会增加存储开销和查询复杂度。仅在确实需要存储多种数据类型时使用,如配置表中的值。
性能考虑
- 避免使用大数据类型:大数据类型(如 varchar(max)、varbinary(max))会增加存储开销和查询时间
- 合理使用索引:某些数据类型不适合创建索引,如 text、image、xml 等
- 避免在 where 子句中对列进行类型转换:会导致索引失效
- 使用适当的精度:对于 decimal 类型,选择合适的精度和小数位数,避免过度使用高精度
最佳实践总结
- 根据实际数据范围选择最小的合适数据类型
- 优先使用精确数值类型存储财务数据
- 根据国际化需求选择字符串类型
- 优先使用增强日期时间类型
- 避免使用过时的数据类型
- 合理使用特殊数据类型
- 考虑性能影响,避免滥用大数据类型
- 根据业务场景选择合适的主键数据类型
