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函數在日期轉換時有用,可以指定日期格式。