在創建表時,必須為表中的每列指派一種數據類型。本節將介紹SQL Server中最常用的一些數據類型。即使創建自定義數據類型,它也必須基於一種標准的SQL Server數據類型。例如,可以使用如下語法創建一種自定義數據類型(Address),但要注意,它基於SQL Server標准的varchar數據類型。
- CREATE TYPE Address
- FROM varchar(35) NOT NULL
如果在SQL Server Management Studio的表設計界面中更改一個大型表中某列的數據類型,那么該操作可能需要很長時間。可以通過在Management Studio界面中腳本化這種改變來觀察其原因。Management Studio再創建一個臨時表,采用像tmpTableName這樣的名稱,然后將數據復制到該表中。最后,界面刪除舊表並用新的數據類型重命名新表。當然,此過程中還涉及其他一些用於處理表中索引和其他任何關系的步驟。
如果有一個包含數百萬條記錄的大型表,則該過程可能需要花費十分鍾,有時可能是數小時。為避免這種情況,可在查詢窗口中使用簡單的單行T-SQL語句來更改該列的數據類型。例如,要將Employees表中JobTitle列的數據類型改為varchar(70),可以使用如下語法。
- ALTER TABLE HumanResources.Employee ALTER COLUMN JobTitle Varchar(70)
說明:
在轉換為與當前數據不兼容的數據類型時,可能丟失重要數據。例如,如果要將包含一些數據(如15.415)的numeric數據類型轉換為integer數據類型,那么15.415這個數據將四舍五入為整數。
您可能想對SQL Server表編寫一個報表,顯示表中每列的數據類型。完成這項任務的方法有很多種,但最常見的一種方法是連接sys.objects表和sys.columns表。在下面的代碼中,有兩個函數可能不太為您所熟悉。函數TYPE_NAME()將數據類型id轉換為適當的名稱。要進行反向操作,可使用TYPE_ID()函數。需要注意的另一個函數是SCHEMA_ID(),它用於返回架構的標識值。在需要編寫有關SQL Server元數據的報表時,這是特別有用的。
- SELECT o.name AS ObjectName,
- c.name AS ColumnName,
- TYPE_NAME(c.user_type_id) as DataType
- FROM sys.objects o JOIN sys.columns c
- ON o.object_id = c.object_id
- WHERE o.name ='Department'
- and o.Schema_ID = SCHEMA_ID('HumanResources')
該代碼返回如下結果(注意,Name是一種用戶定義的數據類型)。
- ObjectName ColumnName DataType
- ---------------------------------------------------
- Department DepartmentID smallint
- Department Name
Name - Department GroupName Name
- Department ModifiedDate
datetime
1. 字符數據類型
字符數據類型包括varchar、char、nvarchar、nchar、text以及ntext。這些數據類型用於存儲字符數據。varchar和char類型的主要區別是數據填充。如果有一表列名為FirstName且數據類型為varchar(20),同時將值Brian存儲到該列中,則物理上只存儲5個字節。但如果在數據類型為char(20)的列中存儲相同的值,將使用全部20個字節。SQL將插入拖尾空格來填滿20個字符。
如果要節省空間,那么為什么還使用char數據類型呢?使用varchar數據類型會稍增加一些系統開銷。例如,如果要存儲兩字母形式的州名縮寫,則最好使用char(2)列。盡管有些DBA認為應最大可能地節省空間,但一般來說,好的做法是在組織中找到一個合適的閾值,並指定低於該值的采用char數據類型,反之則采用varchar數據類型。通常的原則是,任何小於或等於5個字節的列應存儲為char數據類型,而不是varchar數據類型。如果超過這個長度,使用varchar數據類型的好處將超過其額外開銷。
nvarchar數據類型和nchar數據類型的工作方式與對等的varchar數據類型和char數據類型相同,但這兩種數據類型可以處理國際性的Unicode字符。它們需要一些額外開銷。以Unicode形式存儲的數據為一個字符占兩個字節。如果要將值Brian存儲到nvarchar列,它將使用10個字節;而如果將它存儲為nchar(20),則需要使用40字節。由於這些額外開銷和增加的空間,應該避免使用Unicode列,除非確實有需要使用它們的業務或語言需求。
接下來要提的數據類型是text和ntext。text數據類型用於在數據頁內外存儲大型字符數據。應盡可能少地使用這兩種數據類型,因為可能影響性能但可在單行的列中存儲多達2GB的數據。與text數據類型相比,更好的選擇是使用varchar(max)類型,因為將獲得更好的性能。另外,text和ntext數據類型在SQL Server的一些未來版本中將不可用,因此現在開始還是最好使用varchar(max)和nvarchar(max)而不是text和ntext數據類型。
表1-1列出了這些類型,對其作了簡單描述,並說明了要求的存儲空間。
表1-1
數 據 類 型 |
描 述 |
存 儲 空 間 |
Char(n) |
N為1~8000字符之間 |
n字節 |
Nchar(n) |
N為1~4000 Unicode字符之間 |
(2n字節)+2字 節額外開銷 |
Ntext |
最多為230–1 (1 073 741 823)Unicode字符 |
每字符2字節 |
Nvarchar(max) |
最多為230–1 (1 073 741 823)Unicode字符 |
2×字符數+2字 節額外開銷 |
Text |
最多為231–1 (2 147 483 647)字符 |
每字符1字節 |
Varchar(n) |
N為1~8000字符之間 |
每字符1字節+2 字節額外開銷 |
Varchar(max) |
最多為231–1(2 147 483 647)字符 |
每字符1字節+2 字節額外開銷 |
2. 精確數值數據類型
數值數據類型包括bit、tinyint、smallint、int、bigint、numeric、decimal、money、float以及real。這些數據類型都用於存儲不同類型的數字值。第一種數據類型bit只存儲0或1,在大多數應用程序中被轉換為true或false。bit數據類型非常適合用於開關標記,且它只占據一個字節空間。其他常見的數值數據類型如表1-2所示。
表1-2
數 據 類 型 |
描 述 |
存 儲 空 間 |
bit |
0、1或Null |
1字節(8位) |
tinyint |
0~255之間的整數 |
1字節 |
smallint |
–32 768~32 767之間的整數 |
2字節 |
int |
–2 147 483 648~ 2 147 483 647之間的整數 |
4字節 |
bigint |
–9 223 372 036 854 775 808~ 9 223 372 036 854 775 807 之間的整數 |
8字節 |
(續表)
數 據 類 型 |
描 述 |
存 儲 空 間 |
numeric(p,s)或 decimal(p,s) |
–1 038+1~1 038–1之間的數值 |
最多17字節 |
money |
–922 337 203 685 477.580 8~ 922 337 203 685 477.580 7 |
8字節 |
smallmoney |
–214 748.3648~2 14 748.3647 |
4字節 |
SQL Server 2008數據類型(2)
如decimal和numeric等數值數據類型可存儲小數點右邊或左邊的變長位數。Scale是小數點右邊的位數。精度(Precision)定義了總位數,包括小數點右邊的位數。例如,由於14.88531可為numeric(7,5)或decimal(7,5)。如果將14.25插入到numeric(5,1)列中,它將被舍入為14.3。
3. 近似數值數據類型
這個分類中包括數據類型float和real。它們用於表示浮點數據。但是,由於它們是近似的,因此不能精確地表示所有值。
float(n)中的n是用於存儲該數尾數(mantissa)的位數。SQL Server對此只使用兩個值。如果指定位於1~24之間,SQL就使用24。如果指定25~53之間,SQL就使用53。當指定float()時(括號中為空),默認為53。
表1-3列出了近似數值數據類型,對其進行簡單描述,並說明了要求的存儲空間。
表1-3
數 據 類 型 |
描 述 |
存 儲 空 間 |
float[(n)] |
–1.79E+308~–2.23E– 308,0,2.23E–308~1.79E+308 |
N< =24-4字節 N> 24-8字節 |
real() |
–3.40E+38~–1.18E– 38,0,1.18E–38~3.40E+38 |
4字節 |
注意:
real的同義詞為float(24)。
4. 二進制數據類型
如varbinary、binary、varbinary(max)或image等二進制數據類型用於存儲二進制數據,如圖形文件、Word文檔或MP3文件。其值為十六進制的0x0~0xf。image數據類型可在數據頁外部存儲最多2GB的文件。image數據類型的首選替代數據類型是varbinary(max),可保存最多8KB的二進制數據,其性能通常比image數據類型好。SQL Server 2008的新功能是可以在操作系統文件中通過FileStream存儲選項存儲varbinary(max)對象。這個選項將數據存儲為文件,同時不受varbinary(max)的2GB大小的限制。
表1-4列出了二進制數據類型,對其作了簡單描述,並說明了要求的存儲空間。
表1-4
數 據 類 型 |
描 述 |
存 儲 空 間 |
Binary(n) |
N為1~8000十六進制數字之間 |
n字節 |
Image |
最多為231–1 (2 147 483 647)十六進制數位 |
每字符1字節 |
Varbinary(n) |
N為1~8000十六進制數字之間 |
每字符1字節 +2字節額外開銷 |
Varbinary(max) |
最多為231–1 (2 147 483 647)十六進制數字 |
每字符1字節 +2字節額外開銷 |
5. 日期和時間數據類型
datetime和smalldatetime數據類型用於存儲日期和時間數據。smalldatetime為4字節,存儲1900年1月1日~2079年6月6日之間的時間,且只精確到最近的分鍾。datetime數據類型為8字節,存儲1753年1月1日~9999年12月31日之間的時間,且精確到最近的3.33毫秒。
SQL Server 2008有4種與日期相關的新數據類型:datetime2、dateoffset、date和time。通過SQL Server聯機叢書可找到使用這些數據類型的示例。
datetime2數據類型是datetime數據類型的擴展,有着更廣的日期范圍。時間總是用時、分鍾、秒形式來存儲。可以定義末尾帶有可變參數的datetime2數據類型--如datetime2(3)。這個表達式中的3表示存儲時秒的小數精度為3位,或0.999。有效值為0~9之間,默認值為3。
datetimeoffset數據類型和datetime2數據類型一樣,帶有時區偏移量。該時區偏移量最大為+/-14小時,包含了UTC偏移量,因此可以合理化不同時區捕捉的時間。
date數據類型只存儲日期,這是一直需要的一個功能。而time數據類型只存儲時間。它也支持time(n)聲明,因此可以控制小數秒的粒度。與datetime2和datetimeoffset一樣,n可為0~7之間。
表1-5列出了日期/時間數據類型,對其進行簡單描述,並說明了要求的存儲空間。
表1-5
數 據 類 型 |
描 述 |
存 儲 空 間 |
Date |
9999年1月1日~12月31日 |
3字節 |
Datetime |
1753年1月1日~9999年12月31日, 精確到最近的3.33毫秒 |
8字節 |
Datetime2(n) |
9999年1月1日~12月31日 0~7之間的N指定小數秒 |
6~8字節 |
Datetimeoffset(n) |
9999年1月1日~12月31日 0~7之間的N指定小數秒+/–偏移量 |
8~10字節 |
SmalldateTime |
1900年1月1日~2079年 6月6日,精確到1分鍾 |
4字節 |
Time(n) |
小時:分鍾:秒.9999999 0~7之間的N指定小數秒 |
3~5字節 |
6. 其他系統數據類型
還有一些之前未見過的數據類型。表1-6列出了這些數據類型。
表1-6
數 據 類 型 |
描 述 |
存 儲 空 間 |
Cursor |
包含一個對光標的引用和 可以只用作變量或存儲過程參數 |
不適用 |
Hierarchyid |
包含一個對層次結構中位置的引用 |
1~892字節+2 字節的額外開銷 |
SQL_Variant |
可能包含任何系統數據類 型的值,除了text、ntext、 image、timestamp、xml、 varchar(max)、nvarchar(max)、 varbinary (max)、sql_variant以 及用戶定義的數據類型。最大尺 寸為8000字節數據+16字節 (或元數據) |
8016字節 |
Table |
用於存儲用於進一步處理的數 據集。定義類似於Create Table。 主要用於返回表值函數的結果集, 它們也可用於存儲過程和批處理中 |
取決於表定 義和存儲的行數 |
Timestamp or Rowversion |
對於每個表來說是唯一的、自 動存儲的值。通常用於版本戳, 該值在插入和每次更新時自動改變 |
8字節 |
Uniqueidentifier |
可以包含全局唯一標識符 (Globally Unique Identifier, GUID)。guid值可以從Newid() 函數獲得。這個函數返回的值對 所有計算機來說是唯一的。 盡管存儲為16位的二進制值, 但它顯示為char(36) |
16字節 |
XML |
可以以Unicode或非Unicode形式存儲 |
最多2GB |
注意:
cursor數據類型可能不用於Create Table語句中。
hierarchyid列是SQL Server 2008中新出現的。您可能希望將這種數據類型的列添加到這樣的表中--其表行中的數據可用層次結構表示,就像組織層次結構或經理/雇員層次結構一樣。存儲在該列中的值是行在層次結構中的路徑。層次結構中的級別顯示為斜杠。斜杠間的值是這個成員在行中的數字級別,如/1/3。可以運用一些與這種數據類型一起使用的特殊函數。
XML數據存儲XML文檔或片段。根據文檔中使用UTF-16或是UTF-8,它在尺寸上像text或ntext一樣存儲。XML數據類型使用特殊構造體進行搜索和索引。第15章將更詳細地介紹這些內容。
7. CLR集成
在SQL Server 2008中,還可使用公共語言運行庫(Common Language Runtime,CLR)創建自己的數據類型和存儲過程。這讓用戶可以使用Visual Basic或C#編寫更復雜的數據類型,以滿足業務需求。這些類型被定義為基本的CLR語言中的類結構。第8章將更詳細地介紹其管理部分的內容。