1. 数据类型分类
1.1. 整型
1.1.1. 概述
在SQL Server 2000中整型按照数据范围从小到大分为: bit, tinyint, smallint, int, bigint。
1.1.2. 详细描述
数据类型 | 取值范围 | 描述 | 备注 |
bit | 0, 1, NULL | 1. 不能对bit类型建立索引 2. bit类型最多占用1个字节。 | SQL server会优化bit类型存储,如果一个表中有不多于 8个的 bit 列,这些列将作为一个字节存储。如果表中有 9 到 16个 bit 列,这些列将作为两个字节存储。更多列的情况依此类推。 |
tinyint | 从 0 到 255 的整型数据。 | 占用1个字节 | 适合于做一些状态记录 |
smallint | 从-32768到32767之间的整数。 | 占用2个字节 | 适合于做一些状态记录以及小的数据记录。 对应于Java中的short类型,但在SMP的实际使用中将其映射为Integer类型 |
int | 从 -2^31 (-2,147,483,648)到 2^31 - 1 (2,147,483,647)的整型数据(所有数字)。 | 占用4个字节 | 对应于Java中的Integer类型。可以保存大多数的数字 |
bigint | 从 -2^63 (-9223372036854775808) 到2^63-1 (9223372036854775807) 的整型数据(所有数字)。 | 占用8个字节 | 对应于Java中的Long型数据。 |
1.1.3. 小结
SQL Server2000 中最常使用的是int类型,tinyint和smallint在计算时如果发生溢出,会自动转换成范围更大的类型进行计算,但int不会隐式转换为bigint类型。
1.1.4. 示例
declare @numInt int declare @numTinyInt tinyint declare @numSmallint smallint
set @numInt = 2147483647 set @numTinyInt = 255 set @numSmallint = 32767
print @numInt + 1 -- 出现溢出错误 print @numTinyInt + 1 print @numSmallint + 1 |
1.2. 精确浮点型
1.2.1. 概述
浮点类型有两种,一种是decimal,一种是numeric。
1.2.2. 详细描述
数据类型 | 取值范围 | 描述 | 备注 |
decimal[(p[, s])] | 使用最大精度时,有效值从- 10^38 +1 到 10^38 - 1。 | p(精度):小数点左边和右边能存储十进制数字的最大个数。最大为38 s(小数位数): 小数点右边能存储十进制数字的个数。 p和s之间的关系: 0<=s<=p<=38 | 两者完全一样,可以互相赋值,但如果精度或小数位数不同,会丢失精度。 |
numeric[(p[, s])] |
decimal数据类型的大小和精度关系如下:
精度 | 存储字节数 |
1 - 9 | 5 |
10-19 | 9 |
20-28 | 13 |
29-38 | 17 |
1.2.3. 示例
declare @numDec decimal(3, 2) declare @numNum numeric(3, 1)
set @numDec = 1.5 set @numNum = @numDec
-- 完全一致 print @numNum
set @numDec = 1.55 set @numNum = @numDec
-- 丢失精度 print @numNum |
1.3. 货币类型
1.3.1. 概述
用来表示金融或货币的数据类型,有smallmoney和money两种。
1.3.2. 详细描述
数据类型 | 取值范围 | 描述 | 备注 |
smallmoney | -214,748.3648 与+214.748,3647。 | 4个字节 | 精确到货币单位的千分之十。 |
money | 货币数据值介于 -2^63 (-922,337,203,685,477.5808) 与2^63 - 1 (+922,337,203,685,477.5807) 之间。 | 8个字节 | 精确到货币单位的千分之十。 |
1.3.3. 小结
在使用中货币类型完全可以使用精确浮点类型代替,可能在一些特殊的应用程序中可以用到,大部分情况下使用精确浮点类型扩展性更好些。
1.4. 近似浮点型
1.4.1. 概述
用于表示浮点数字数据的近似数字数据类型。浮点数据为近似值;并非数据类型范围内的所有数据都能精确地表示,但可以表述的数据范围极大。
1.4.2. 详细描述
数据类型 | 取值范围 | 描述 | 备注 |
float[(n)] | 从 - 1.79E + 308 到 1.79E + 308之间的浮点数字数据。 | n表示使用科学记数法时尾数的位数,同时指示其精度和存储大小。n的取值范围是0~53 | double表示float(53) |
real | 从 -3.40E + 38 到 3.40E + 38 之间的浮点数字数据。 | 4字节. | 在 SQL Server中,real 的同义词为 float(24)。 |
占用空间大小:
n 所在范围 | 精度 | 存储大小 |
1-24 | 7 位数 | 4 字节 |
25-53 | 15 位数 | 8 字节 |
1.4.3. 两种浮点类型之间的比较
| 精确浮点类型 | 近似浮点类型 |
表示方式 | 每一个十进制位都表示一个精确的数字,不需要近似 | 当需要表示的数字超过限制后,会对尾数进行四舍五入 |
精度 | 完全精确 | 在一定范围内可以精确标识,超出范围后会发生舍入 |
表示范围 | 最多只有38位 | 可以表示数量级为10^302数量级的数据 |
1.5. 日期和时间
1.5.1. 概述
用来保存日期和时间,有datetime和smalldatetime两种。
1.5.2. 详细描述
数据类型 | 取值范围 | 描述 | 备注 |
datetime | 从 1753 年 1 月 1 日到 9999 年12 月 31 日的日期和时间数据. 精确度为百分之三秒(等于 3.33 毫秒或 0.00333 秒)。 | 两个4字节组成datetime的值,其中4字节保存日期值,另外4个字节保存时间值。 一个datetime占用8个字节 | Microsoft® SQL Server? 拒绝所有其不能识别为 1753 年到 9999 年间的日期的值。 |
smalldatetime | 从 1900 年 1 月 1 日到 2079 年 6月 6 日的日期和时间数据精确到分钟。29.998 秒或更低的smalldatetime 值向下舍入为最接近的分钟,29.999 秒或更高的smalldatetime 值向上舍入为最接近的分钟。 | 两个2字节组成smalldatetime的值,其中2个字节保存日期值,2个字节保存时间值。 一个smalldatetime占用4个字节。 |
|
1.5.3. 示例
时间日期类型舍入示例:
-- 返回 12:35 SELECT CAST('2000-05-08 12:35:29.998' AS smalldatetime) GO -- 返回 12:36 SELECT CAST('2000-05-08 12:35:29.999' AS smalldatetime) GO
-- 1998-01-02 00:00:00.000 select cast('1998-1-1 23:59:59.999' as datetime)
-- 1998-01-01 23:59:59.997 select cast('1998-1-1 23:59:59.995' as datetime) select cast('1998-1-1 23:59:59.996' as datetime) select cast('1998-1-1 23:59:59.997' as datetime) select cast('1998-1-1 23:59:59.998' as datetime)
-- 1998-01-01 23:59:59.993 select cast('1998-1-1 23:59:59.992' as datetime) select cast('1998-1-1 23:59:59.993' as datetime) select cast('1998-1-1 23:59:59.994' as datetime)
-- 1998-01-01 23:59:59.990 select cast('1998-1-1 23:59:59.990' as datetime) select cast('1998-1-1 23:59:59.991' as datetime) |
1.5.4. 小结
一般情况下使用datetime值,因为smalldatetime精度差而且数据范围小,而且只能保存2076年以前的数据。
1.6. 字符串
1.6.1. 概述
在SQL Server 2000中,字符串分为两种,一种是ASCII字符串,另一种是Unicode字符串。
其中ASCII字符串使用三种数据类型表示,分别是char, varchar, text三种类型,而Unicode字符串使用nchar, nvarchar, ntext三种类型表示。
1.6.2. 详细描述
数据类型 | 描述 |
char[(n)] | 长度为 n 个字节的固定长度且非 Unicode 的字符数据。n 必须是一个介于 1 和 8,000 之间的数值。存储大小为 n 个字节。 在定义数据时如果没有指定n,则n默认为1 在cast时如果没有指定n,则n默认为30 |
varchar[(n)] | 长度为 n 个字节的可变长度且非 Unicode 的字符数据。n 必须是一个介于 1 和 8,000 之间的数值。存储大小为输入数据的字节的实际长度,而不是 n 个字节。所输入的数据字符长度可以为零。 在定义数据时如果没有指定n,则n默认为1 在cast时如果没有指定n,则n默认为30 |
text | 服务器代码页中的可变长度非 Unicode 数据的最大长度为 231-1 (2,147,483,647) 个字符。当服务器代码页使用双字节字符时,存储量仍是 2,147,483,647 字节。存储大小可能小于 2,147,483,647 字节(取决于字符串)。 |
nchar | 包含 n 个字符的固定长度 Unicode 字符数据。n 的值必须介于 1 与4,000 之间。存储大小为 n 字节的两倍。 在定义数据时如果没有指定n,则n默认为1 在cast时如果没有指定n,则n默认为30 |
nvarchar | 包含 n 个字符的可变长度 Unicode 字符数据。n 的值必须介于 1 与4,000 之间。字节的存储大小是所输入字符个数的两倍。所输入的数据字符长度可以为零。 在定义数据时如果没有指定n,则n默认为1 在cast时如果没有指定n,则n默认为30 |
ntext | 可变长度 Unicode 数据的最大长度为 230 - 1 (1,073,741,823) 个字符。存储大小是所输入字符个数的两倍(以字节为单位)。 |
1.6.3. 小结
在实际使用中ASCII字符串可以根据当前字符串中的每一个字符是否能用一个字节表示来决定实际使用的字节数,而Unicode字符串不判断输入字符串中的每一个字节,将所有字符都按照两个字节处理。
1.6.4. Q&A
1. 什么时候使用变长字符串,什么时候使用定长字符串?
当存储数据长度相差很大时,应该使用变长的字符,否则应该使用定长数据。如果需要在字符列中定义索引,最好使用定长数据,因为定长数据的索引效率要高于变长数据。
2. 为什么需要text和ntext数据类型?为什么char, varchar, nchar,nvarchar会有8000个字节的限制?
在SQL Server 2000中,所有数据是保存在数据页中的,每一个数据页的大小是8K,每一个数据必须保存表中的至少一行数据,每一行的数据不能跨页保存,所以char, varchar, nchar,nvarchar四种字符串的最大长度都小于8K字节。如果需要保存8K以上的内容,就需要将这部分的字符串分离到数据页之外独立保存,于是text和ntext数据类型就诞生了。如果在SQL Server 2000 中定义text或ntext类型数据,插入时默认将数据保存到一个文本页中,这个页里面专门用来存储ntext, text和image类型数据,在保存行的数据页中只保留一个指针,用来指向实际的数据。
3. 对于JDBC来说text以及ntext类型在使用上有什么区别?
对JDBC的使用者来说,text和ntext与其他字符串类型没有任何区别,对于JDBC的开发者来说,需要考虑数据缓冲区和分块传输的情况。
1.7. 二进制类型
1.7.1. 概述
SQL Server 2000中可以定义专门用来保存二进制数据的数据类型,分为三种:binary和varbinary,image。
1.7.2. 详细描述
数据类型 | 描述 |
binary[(n)] | 固定长度的 n 个字节二进制数据。N 必须从 1 到 8,000。存储空间大小为 n+4 字节。 |
varbinary[(n)] | n 个字节变长二进制数据。n 必须从 1 到 8,000。存储空间大小为实际输入数据长度 +4 个字节,而不是 n 个字节。输入的数据长度可能为 0 字节。在 SQL-92 中 varbinary 的同义词为 binary varying。 |
image | 可变长度二进制数据介于 0 与 231-1 (2,147,483,647) 字节之间。 |
1.7.3. 小结
1. 从二进制类型占用空间可以看出,二进制类型在SQL Server 2000 的页文件中分为两部分保存,有4个字节保存数据长度,剩余部分是数据内容。
2. 如果定义数据时没有指定n,默认为1;cast时没有指定n,默认为30。image的存储方式和text,ntext类型一致。
1.7.4. Q&A
1. 如何使用JDBC访问binary,varbinary以及image类型的数据?
和其他类型完全一致。
1.8. 其他数据类型
除了以上描述的几种数据类型之外,SQL Server 2000中还有几种特殊的数据类型。
1.8.1. cursor:游标类型
游标类型,可以定义为变量或存储过程的OUTPUT参数,但不能定义为表或视图中的列。
使用游标需要经过定义,打开,使用,关闭,销毁五个过程,对于同一个SQL Server 连接来说,游标属于全局资源,如果定义后不销毁或没关闭,容易造成内存泄漏。
-- 定义游标 declare hiRuleName_cursor cursor for select hiRuleName from T_HI_RULE
-- 打开游标 open hiRuleName_cursor
fetch next from hiRuleName_cursor
declare @hiRuleName varchar(32) fetch next from hiRuleName_cursor into @hiRuleName select @hiRuleName
-- 关闭游标 close hiRuleName_cursor
-- 删除游标 deallocate hiRuleName_cursor |
1.8.2. sql_variant:变体类型
可以用来保存SQL Server中的任何类型数据(text、ntext、image、timestamp 和 sql_variant 除外)。可以用在表或视图的列,局部变量以及存储过程或函数中。
在使用时需要首先转换成相应的类型,类似Java中的Object类。
在SQL server 2000中使用sql_varaint类型:
-- 创建临时表 create table #t( value sql_variant )
-- 在表中插入不同类型的数据 insert into #t(value) values(123) insert into #t(value) values(1.5) insert into #t(value) values('feawfe')
-- 查询 select * from #t
-- 将其中任意一行修改为另一种数据类型 update #t set value='111' where value=123
-- 查询 select * from #t
-- 删除表 drop table #t |
在JDBC中如何使用sql_variant类型?
和其他类型完全一致。
1.8.3. table:表格类型
以表格的方式保存计算结果便于后续处理。
使用表格的数据类型不但可以返回二维数组,而且返回值也可以象一张真实的表一样拥有列类型,主键,唯一性约束,CHECK约束,默认值等。
table类型和临时表相比,有以下几个优点:
l table变量是局部变量,有明确的作用域,超过作用域变量自动清除。
l 在存储过程中使用table变量,不需要重新编译。
l 涉及table变量更新的事务只在table变量更新期间存在,减少table变量对锁定和记录资源的需求。
使用table类型局部变量:
declare @tb table( c1 bigint primary key , -- 定义主键 c2 varchar(32) not null unique, -- 定义唯一非空列 c3 int check(c3 < 5 and c3 > 0) -- 定义check约束 )
-- 插入时没有违反约束 insert into @tb(c1, c2, c3) values(1, '123', 3) select * from @tb
-- 违反主键唯一性约束 insert into @tb(c1, c2, c3) values(1, '123', 3)
-- 违反c2非空约束 insert into @tb(c1, c2, c3) values(2, null, 3)
-- 违反c3 check约束 insert into @tb(c1, c2, c3) values(2, '123', 8) |
1.8.4. timestamp:时间戳
自动生成的二进制数,确保这些数据在数据库中是唯一的。占用8个字节。
时间戳用于表示 SQL Server 在一行上的活动顺序,按二进制格式以递增的数字来表示。当表中的行发生变动时,用从 @@DBTS 函数获得的当前数据库的时间戮值来更新时间戮。timestamp 数据与插入或修改数据的日期和时间无关。若要自动记录表中数据更改的时间,使用 datetime 或 smalldatetime 数据类型记录事件或触发器。
创建表时可以不为timestamp类型指定列名,SQL Server 2000 会自动生成一个列名。
一个表只能有一个timestamp列,每次插入或更新包含timestamp列的行时,时间戳列会自动更新。
-- 创建临时表 create table #t( value varchar(32), timestamp )
-- 查看当前时间戳 select @@DBTS
insert into #t(value) values('aaa') insert into #t(value) values('bbb') insert into #t(value) values('ccc')
select * from #t
-- 更新 update #t set value='bbb'
select * from #t
drop table #t |
1.8.5. uniqueidentifier:(全局统一标识符)
一个36字节的十六进制字符串,可以作为表的主键。
一般使用newid()方法随机生成。
2. 自定义数据类型
2.1. 概述
在SQL Server 2000 中允许用户自定义数据类型,定义自定义数据类型时,需要提供以下三个参数:
l 名称
l 数据类型
l 为空性
如果用户自定义数据类型在module数据库中创建,将作为全局的数据类型出现,在其他的所有数据库中都可见,如果在其他数据库中定义,只在相应的数据库中看到。
2.2. 详细描述
创建用户自定义数据类型,使用系统存储过程sp_addtype,删除用户自定义数据类型,使用系统存储过程sp_droptype。
SQL Server 2000 中大多数数据类型都可以用来创建新的数据类型(除了cursor,table,timestamp之外)。
2.3. 示例
EXEC sp_addtype telephone, 'varchar(32)', 'NOT NULL' exec sp_droptype telephone |
2.4. 小结
使用自定义数据类型,可以在开发的初期形成一套开发规范,所有人都使用自定义数据类型进行数据库定义,不容易出现名称类型或长度不一致的情况。
3. 数据类型之间的转换
3.1. 概述
数据类型的转换分为隐式转换和显示转换两种。
l 隐式转换不可见,系统自动进行。
l 显示转换使用cast或convert函数进行。
3.2. cast和convert函数
两个函数都是用来显示转换数据类型的,其中cast是遵循SQL-92标准,大多数时候已经足够,convert函数在日期转换时有用,可以指定日期格式。