- 數據類型的選擇幫助優化查詢,比如針對int類型列和針對文本類型列可能會生成完全不同的查詢計划
- 三種數據類型:
- 系統數據類型
- 別名數據類型:用戶可以為系統數據類型提供一個別名,並且可以對數據類型做進一步限制,這樣可以保持數據庫和應用程序的一致性
- 用戶自定義數據類型:引入的托管代碼中的數據類型,包括CLR中的系統數據類型和CLR中用戶自定義數據類型
- 整數數據類型:
- tinyint存儲的是一個字節(8位),值范圍是0-255
- smallint存儲的是兩字節(16位),值范圍是-32768-32767
- int存儲的是四字節(32位),值范圍是-2147483648-2147483647
- bigint存儲的是八字節,值范圍是-2^63 - 2^63-1,存儲的是非常大的整數值
- 分數數據類型:
- decimal:ANSI兼容,允許指定整數位和小數位
- numeric:功能上和decimal是一樣的
- money、smallmoney:以前遺留下來的數據類型,用來存儲貨幣值,四個小數位精度,通常使用decimal代替這個數據類型
- bit數據類型:存儲1位值,存儲上有優化,如果一張表中少於8個的bit列,他們將被存儲在一個字節中,通常用來存儲boolean值;在SQL Server中bit值沒有字符串形式,True和False只是可以轉化為bit值,就像整數值1、0可以轉化為bit值一樣,底層bit值存儲的不是True或False,也不是整數值1、0,而只是一位值而已;高級語言中False都使用0來存儲,而True存儲根據語言不同使用不同的值,因此在檢測boolean值時,使用@inputvalue=0來檢測false,使用@inputvalue<>0來檢測true,不要使用@inputvalue=1來檢測true值,在有的語言中得不到預期的結果;bit類型值還可以存儲null值,也就是說bit類型值共有三種狀態0,1,null
- IDENTITY和int或者bitint列一起使用,通過SET IDENTITY_INSERT ON開關,允許在IDENTITY列顯式插入值,具有IDENTITY屬性的列不能夠保證值都唯一,因為可以顯式插入值;可以通過系統變量@@IDENTITY檢索最近一次IDENTITY值,使用@@IDENTITY的問題是:當插入一條記錄到Customer表中時,這個customer被賦予一個新的identity,但是如果這個表有一個觸發器,這個觸發器在插入時將這個條目寫入到audit logging table中,@@IDENTITY返回的是logging table值,而不是Customer表的值;此時需要使用SCOPE_IDENTITY函數,它提供的是當前范圍Scope內最新identity值;當一次插入多行記錄時,通過OUTPUT語句檢索IDENTITY值(通過檢索inserted表來檢索該值),插入一條記錄時,使用這種方法也可以檢索插入的值
- 近似數據類型通常用在科學計算應用程序中,而不是商業應用程序中,不要使用近似數據類型存儲貨幣值這樣的商業值
- real:存儲的是4字節(32位),精確到7位小數
- float(n):n代表用來存儲尾數的位數,n默認等於53,當n在1-24范圍時,n=24,即精度為7位小數,使用4字節存儲,也就是real數據類型的值;當n在25-53范圍時,n=53,即精度15位小數,使用8字節存儲
- SQL Server支持豐富的日期和時間數據類型,需要非常小心每個類型的字符串形式,大量函數可用來處理這些類型
- date:符合ANSI標准,范圍0001-01-01 to 9999-12-31,精確到天
- time:符合ANSI SQL標准,范圍00:00:00.0000000 to 23:59:59.9999999,精確到100納秒,允許指定小數位數,即定義納秒的位數
- datetime2:是date和time類型的組合
- datetime:舊版本的日期時間類型,范圍1753-01-01 to 9999-12-31,精確到3.33毫秒,datetime類型根據語言設置將字符串轉化為日期,"YYYYMMDD"總是可以轉化為正確的日期時間類型,"YYYY-MM-DD"可能會被當做"YYYY-DD-MM"格式進行轉化,取決於設置,date類型不會有這樣的行為
- datetimeoffset: datetime2和timezone offset的組合,日期時間部分代表本地時間,timezone offset范圍-14:00 to +14:00,表示和UTC時間的偏移量,注意date類型是和時區無關的
- GUID就是一個數字分配器,保證一個程序生成的值和其他程序生成的值不沖突,是128位值;在SQL Server中對應的數據類型就是uniqueidentifier,該類型允許的操作只包括=、<>、<、>、<=、>=以及是否為null的檢測IS NULL 、IS NOT NULL;該數據類型定義的列上不允許使用IDENTITY;通過NEWID()函數生成新的GUID值,該函數生成的GUID值具有非常大的隨機性,有性能問題,NEWSEQUENTIALID()函數試圖解決NEWID()函數的隨機性,不過它是以犧牲唯一性為代價的
- NULL是數據庫列的狀態,不是數據類型的值,使用IS NULL檢測是否為null,而不是使用=NULL檢測是否等於null;為數據庫列指定不當的nullability是常見的設計錯誤
- Unicode常量要求在前面都加上N前綴,使用LEN()函數返回字符的數量,使用DATALENGTH()返回字節數量
- 字符數據類型:
- char和nchar:存儲固定長度的字符,如果這兩個類型值的字符長度不夠的話,在尾部使用空格填充,使用時通常都需要去掉尾部的空格,char使用單字節存儲,nchar采用雙字節存儲
- varchar和nvarchar:用來存儲變長字符串,允許你指定一個字符串的最大長度,nvarchar用來存儲unicode字符(即雙字節字符),varchar和nvarchar限制在8000和4000個字符上限,正好是數據庫中一個數據頁的大小
- varchar(max)和nvarchar(max):存儲更長的字符,它們允許存儲高達2GB的數據
- text和ntext:舊數據類型,被啟用,使用varchar(max)和nvarchar(max)替換這兩個數據類型
- sysname:SQL Server中對象名稱通常都是該類型,是nvarchar(128)的別名
- Collation用來控制在SQL Server中存儲的非Unicode數據使用的代碼頁,以及SQL Server中排序和比較字符值時使用的規則
- code pages代碼頁:在計算機中每個字符使用一個字節,共有256個字符,0-31作為控制字符,比如回車(8)、Tab(9)、空格(32),一直到Delete(127);127以上的值則根據標准不同表示不同的含義,這些標准在MSDOS操作系統中就被稱為代碼頁,一個代碼頁就定義128-255之間的字符的用途,這些代碼頁0-127之間的字符定義都是相同的
- 共有兩類Collations:SQL Server Collations和Windows Collations,SQL Server Collations用來保持向后兼容性,鼓勵使用Windows Collations,SQL Server Collations名稱采用如下形式:SQL_SortRules[_Pref]_CPCodePage_ComparisonStyle
- SortRules:使用的字母表或者語言
- Pref:是否大寫字母優先
- CodePage:代碼頁,1-4位整數,由於歷史原因CP1使用的是1252代碼頁,其他正常
- Comparison Style:BIN表示按二進制排序或者case、accent是否敏感的組合,CI不區分大小寫,CS區分大小寫,AI不區分語調,AS區分語調
- 可以在服務器、數據庫、列級別設置Collations,當比較使用不同的Collations存儲的數據時,要求指定用於比較的Collations
- CAST是ANSI SQL中標准的數據類型轉換操作符,Convert則提供了更加強大的功能,允許你指定如何執行類型轉換,即允許指定轉換的格式Style,注意Style通常是關於字符串輸出的,但是也可以用來處理字符串輸入,即解析字符串
- 盡量避免隱式轉換,因為隱式轉換可能會帶來非期望的結果,隱式轉換經常出現的問題:
- 為目標類型指定了不恰當的值,比如不恰當字符串轉換為int值
- 為目標類型指定值超出了該類型的范圍,比如為tinyint類型指定了300
- 在轉換時值被截斷(有時是悄悄的),比如CONVERT(varchar(6),SYSDATETIME(),112),112格式通常返回8位字符串,當轉換為6位字符串時,就被悄悄截斷
- 在轉換時值被舍入(有時是悄悄的),比如datetime類型值20051231 23:59:59.999被悄悄轉換為20060101 00:00:00.000
- 在轉換時值被修改(有時是悄悄的),SELECT 5ee,被悄悄修改為5
- 對數據類型內部存儲做假設,依賴於數據類型內部存儲是非常危險的,因為內部表示隨着時間會發生變化
- 一些日期類型轉換依賴於語言設置,比如2010-05-04即可以轉換為2010年5月4日,也可以轉換為2010年4月5日
- 有一些解析問題難以理解,比如SELECT 5ee
- rowversion數據類型是用來幫助處理並發的,之前SQL Server使用的是timestamp,現在timestamp已經被棄用;在每次修改數據行時,rowversion值都自動被修改,當你要提交數據修改時,首先檢查是否存在rowversion值的行,如果不存在,則說明數據已經被修改,此時在使用相應的策略,注意這里存在竟態條件,即你檢查時沒有發現數據被修改,但是提交前數據卻被修改;rowversion在數據庫中保存一個計數器,所有修改都會讓計數器增加,可以使用系統變量@@DBTS檢索返回的rowversion值
- Alias data types就是系統內置數據類型的子類型,使用CREATE TYPE語句創建,包含了是否可以為null的說明,通常用來維護應用程序中使用的數據類型的一致性(比如定義了ProductNum類型,其為nvarchar(20),則使用ProductNum定義的列都是nvarchar(20),不會出現在一個表中product number是nvarchar(20),在另一個表中是nvarchar(22));數據庫公共角色都自動被授予對Alias data types的REFERENCES權限,即公共角色都自動可以引用創建的Alias data types
- 其他數據類型:
- binary、varbinary、varbinary(max):用來存儲任意的大的二進制對象(blobs)
- image:已經被遺棄,應該使用varbinary(max)
- hierarchyid:是在托管代碼中實現的,代表樹中的節點
- sql_variant:用來存儲未知類型的數據,很少使用
- xml
- cursor:在構造基於游標的代碼時,保存對游標的引用
- table:保存整個結果集
- geometry、geography
