SQL Server做爲一個國際化產品,支持多語言環境。在SQL Server中,字符集被稱爲排序規則(即Collation)。排序規則不只影響記錄行的sort順序,還影響中文顯示是否亂碼等。在SQL Server中,排序規則可在3處地方設置:sql
服務器級別 =>instances
db庫級別 =>databases
表列級別 =>columns數據庫
上圖所示爲SQL Server默認狀況下對Collation繼承的方式。服務器
即在SQL Server軟件安裝時咱們可設置服務器級別的排序規則,也就是instances的排序規則。以下所示是使用T-SQL查詢當前instances的排序規則信息:spa
--查詢當前SQL Server服務器的排序規則 SELECT SERVERPROPERTY(N'Collation') -------------------------------------------------- Chinese_PRC_CI_AS
固然你也可使用SSMS查看服務器屬性:
.net
若在建立databases時咱們未指定排序規則,databases則會使用instances的排序規則。以下所示是經過sql代碼查詢或修改SQL Server中databases的排序規則信息:code
--在建立database時指定排序規則:SQL_Latin1_General_CP1_CI_AS USE master; GO CREATE DATABASE mydb COLLATE SQL_Latin1_General_CP1_CI_AS GO --經過目錄視圖sys.databases查詢databases的排序規則 SELECT name, collation_name FROM sys.databases WHERE name = N'mydb'; ------------------------------------------------- mydb SQL_Latin1_General_CP1_CI_AS --修改現有databases的排序規則 ALTER DATABASE mydb COLLATE Chinese_PRC_CI_AS
而表中的列(columns)默認狀況是繼承databases的排序規則(除非在建立表時對列的排序規則進行指定),咱們可經過目錄視圖sys.columns查詢表中columns的排序規則信息。server
這裏需注意:SQL Server的排序規則隻影響字符型的列,如char, varchar, text, nchar, nvarchar, ntext,所以目錄視圖sys.columns中非字符型的排序規則顯示爲NULLblog
--注意:只有字符型的列纔會顯示排序規則信息,非字符型的顯示爲NULL SELECT name, collation_name FROM sys.columns where collation_name is NOT NULL
在安裝SQL Server時,你可能困惑應該選擇哪一種字符集,SQL Server或者Windows的。官方推薦使用SQL Server的字符集,而非Windows的字符集。緣由是,SQL Server字符集是基於Windows衍生出來的,同時保證SQL Server版本間的兼容性, 如SQL Server 2014可以使用的字符集比2008多排序
--查看當前SQL Server支持的排序規則 SELECT * from ::fn_helpcollations()
注意字符集的名字縮寫與對應的的描述,如CI表示不區分大小寫、 繼承
咱們不難理解:只需保持SQL Server中3處字符集設置的地方:instances、databases、columns設置一致便是正確的使用方式。
那麼當SQL Server中instances與databases對排序規則設置不一致時,將直接致使臨時表#或##不能正常使用(臨時表的列默認繼承tempdb的排序規則,而tempdb則繼承了instances的排序規則)。
/* 注意: 這裏mydb的字符集是SQL_Latin1_General_CP1_CI_AS, 而instance的字符集是Chinese_PRC_CI_AS */ USE mydb; GO --在mydb中建立一張表collation_test CREATE TABLE collation_test (hyper varchar(10)); GO --建立臨時表collation_temp CREATE TABLE #collation_temp (hyper varchar(10)); GO
鏈接查詢上述臨時表的內容時,將出現以下報錯信息:
--查詢報錯 SELECT * FROM collation_test l LEFT JOIN #collation_temp c ON l.hyper = c.hyper; -------------------------------------------- Msg 468, Level 16, State 9, Line 4 沒法解決 equal to 運算中 "Chinese_PRC_CI_AS" 和 "SQL_Latin1_General_CP1_CI_AS" 之間的排序規則衝突。
其根本緣由是因爲表collation_test與臨時表#collation_temp中列的排序規則不一致。雖然能夠經過如下2種方式繼續使用臨時表,但並不推薦。以下經過指定select表中列的排序規則,繼續使用上述兩張表。
--方式1: --注意指定表collation_test使用排序規則COLLATE Chinese_PRC_CI_AS SELECT * FROM collation_test l LEFT JOIN #collation_temp c ON l.hyper COLLATE Chinese_PRC_CI_AS = c.hyper -------------------------------------------------------
第二種解決方法則是在建立表時指定列的排序規則
--方式2 USE mydb; GO --注意指定了列的排序規則:COLLATE Chinese_PRC_CI_AS CREATE TABLE collation_Wang (hyper varchar(10) COLLATE Chinese_PRC_CI_AS); --保持列的排序規則一致便可正常使用臨時表#collation_temp SELECT * FROM collation_wang w LEFT JOIN #collation_temp c ON w.hyper = c.hyper -------------------------------------------------------
同時instances的排序規則設置會影響SQL Server數據的導入導出功能。
一般咱們遇到的另外一個問題是:經過SSMS(即SQL Server Management Studio)插入(insert)的中文,在查詢時顯示亂碼(即問號?)。
--在上述表collation_test插入中文 INSERT INTO collation_test VALUES ('東') --查詢表collation_test的記錄 select * from collation_test
查詢顯示亂碼:
這固然是因爲表collation_test上hyper列的字符集設置不正確所致使的。但若你有幸在表上使用了nvarchar等類型,那麼當出現上述亂碼時,也許你還可使用以下臨時方式補救:
/* 注意: 數據庫mydb依舊是使用錯誤的排序規則:SQL_Latin1_General_CP1_CI_AS, 可是表collation_nvarchar使用了nvarchar類型,而非varchar */ USE mydb; GO CREATE TABLE collation_nvarchar (hyper nvarchar(10)); GO --臨時處理方式 INSERT INTO collation_nvarchar VALUES (N'東'); --錯誤插入方式 INSERT INTO collation_nvarchar VALUES ('東'); --查詢表collation_nvarchar的記錄 select * from collation_nvarchar
綜上述,咱們應儘量的正確設置SQL Server排序規則:
1. 正確的設置SQL Server排序規則 ,保持instances、databases、columns中3處排序規則一致,推薦使用Chinese_PRC_CI_AS
2. 儘量使用nvarchar等Unicode類型,而非varchar類型
Setting and Changing the Database Collation
https://msdn.microsoft.com/en-us/library/ms175835(v=sql.105).aspx
sys.columns (Transact-SQL)
https://msdn.microsoft.com/en-us/library/ms176106(v=sql.120).aspx
Collation and International Terminology
https://msdn.microsoft.com/en-us/library/ms143726(v=sql.105).aspx