MS SQL 排序規則總結


排序規則術語

 

     什么是排序規則呢? 排序規則是根據特定語言和區域設置標准指定對字符串數據進行排序和比較的規則。SQL Server 支持在單個數據庫中存儲具有不同排序規則的對象。MSDN解釋:在 Microsoft SQL Server中,字符串的物理存儲由排序規則控制。排序規則指定表示每個字符的位模式以及存儲和比較字符所使用的規則

當 Transact-SQL 語句在具有不同排序規則設置的不同數據庫上下文中運行時,其運行結果可能會不同。如果可能,請為您的組織使用標准化排序規則。我管理的數據庫當中,一般情況下,中國區域設置為Chinese_PRC_CI_AS,國外一般設置SQL_Latin1_General_CP1_CI_AS。這樣就不必顯式指定每個字符或 Unicode 表達式中的排序規則。如果必須使用具有不同排序規則和代碼頁設置的對象,請對查詢進行編碼,以考慮排序規則的優先順序規則。

排序規則指定了表示每個字符的位模式。它還指定了用於排序和比較字符的規則。排序規則的特征是區分語言、區分大小寫、區分重音、區分假名以及區分全半角。如下所示:

Chinese_PRC_CI_AS   前半部份:指UNICODE字符集,Chinese_PRC_指針對大陸簡體字UNICODE的排序規則,CI表示不區分大小寫,AS表示區分重音。

排序規則的后半部份即后綴 含義:

_BIN         指定使用向后兼容的二進制排序順序。

_BIN2        指定使用 SQL Server 2005 中引入的碼位比較語義的二進制排序順序。

_Stroke      按筆划排序

_CI(CS)      是否區分大小寫,CI不區分,CS區分(case-insensitive/case-sensitive)

_AI(AS)      是否區分重音,AI不區分,AS區分(accent-insensitive/accent-sensitive)

_KI(KS)      是否區分假名類型,KI不區分,KS區分(kanatype-insensitive/kanatype-sensitive)

_WI(WS)      是否區分全半角, WI不區分,WS區分(width-insensitive/width-sensitive)

區分大小寫:如果想讓比較將大寫字母和小寫字母視為不等,請選擇該選項。

區分重音:如果想讓比較將重音和非重音字母視為不等,請選擇該選項。如果選擇該選項,比較還將重音不同的字母視為不等。
區分假名:如果想讓比較將片假名和平假名日語音節視為不等,請選擇該選項。
區分寬度:如果想讓比較將半角字符和全角字符視為不等,請選擇該選項。

查看數據庫支持哪些排序規則可以通過下面系統函數查看:

   1: select * from ::fn_helpcollations();

 

排序規則類型

      

SQL Server 提供了兩組排序規則:Windows 排序規則和 SQL Server 排序規則。具體參考MSDN,這里不做過多贅述。

 

查看服務器排序規則(數據庫實例排序規則)

   1: SELECT SERVERPROPERTY(N'Collation')

 

查看數據庫排序規則

   1: SQL 1:
   2:  
   3: SELECT DATABASEPROPERTYEX('DBMonitor', 'Collation')
   4:  
   5: SQL 2:
   6:  
   7: SELECT name AS [DatabaseName], collation_name AS [Collation] FROM sys.databases;

查看列排序規則

SQL 1:

   1: SELECT c.object_id, c.name, t.name, c.collation_name
   2:  
   3: FROM sys.columns c
   4:  
   5: LEFT JOIN sys.types t on t.system_type_id = c.system_type_id
   6:  
   7: WHERE  object_id=OBJECT_ID('Test');

修改服務器排序規則

 

      修改服務器的排序規則的原因千差萬別,大部分情況是由於安裝的時候,忽略了服務器排序規則這個選項設定,沒有事前規划好,等到將數據庫還原或遷移到新服務器上,測試過程中才發現問題。

修改服務器排序規則,其實就是按指定排序規則重新生成 master、model、msdb 和 tempdb 等系統數據庫,修改服務器排序規則中,首先刪除這些系統數據庫,然后在默認位置按指定排序規則重新創建。 修改數據庫實例排序規則時,由於刪除、重建系統數據庫。 用戶對這些數據庫所做的所有修改都會丟失。 例如,賬號信息、作業、鏈接服務器等等。所以修改服務器排序規則要慎重,首先做好備份或整理相關賬號、作業、鏈接服務器、郵件配置信息等。以免倉促造成不必要的麻煩或損失。

MSDN關於設置和更改服務器排序規則

SQL 2005

   1: start /wait setup.exe /qb INSTANCENAME=MSSQLSERVER REINSTALL=SQL_Engine REBUILDDATABASE=1 SAPWD=test SQLCOLLATION=SQL_Latin1_General_CP1_CI_AI

SQL 2008

   1: Setup /QUIET /ACTION=REBUILDDATABASE /INSTANCENAME=InstanceName  /SQLSYSADMINACCOUNTS=accounts /[ SAPWD= StrongPassword ]  /SQLCOLLATION=CollationName

clip_image002

服務器排序規則修改起來看似很簡單,其實不然,一不小心,就會讓你萬劫不復。我在實踐中就碰到過一次疏忽了某個步驟,結果讓我驚出一身冷汗。下面是我自己實施的步驟:

Step 1: 首先備份數據庫(包括系統數據庫和用戶數據庫)。記得千萬不要漏掉了系統數據庫備份。有備才能無患,否則每一步操作,你總要提心吊膽。

Step 2: 在文檔上記錄下你修改過的一些服務器配置值。例如,在SQL SERVER 2008中,你有可能啟用backup compression default ;在某個32位數據庫開啟了awe enabled 選項,那么修改服務器排序規則后,你需要重新應用、配置這些值。以免遺漏,導致數據庫性能等問題。

Step 3:記錄一下系統數據庫的數據文件和日志文件的所在路徑。 重新生成系統數據庫會將所有系統數據庫安裝到其原位置。 如果你沒有移動過系統數據庫數據庫文件或日志文件,這一步可以忽略,像很多時候,為了I/O性能等原因,可能移動過這些系統數據庫文件和日志文件。

Step 4: 用文檔將登錄名(logins)和相關密碼整理出來。因為修改服務器排序規則,實則重建系統數據庫master、msdb、tempd等,登錄名等信息會全部沒有,需要重新創建、配置。

Step 5: 生成已有作業的SQL腳本。方便修改服務器排序規則后,重新創建、部署作業。道理同上。

Step 6: 生成已有鏈接服務器的排序規則,方便修改服務器排序規則后,重新創建、部署鏈接服務器。道理同上。

Step 7: 整理一下數據庫郵件配置文件和已經創建的賬號,方便修改服務器排序規則后,重新配置。

Step 8: 如果在實例上有配置發布—訂閱等,那么也需要整理這些相關的腳本、文檔。

Step 9: 分離用戶創建的數據庫(這一步其實沒有必要)。

Step 10:修改服務器排序規則

Step 11: 附加Step 9分離的數據庫。

Step 12:解決孤立賬號、配置作業、鏈接服務器…..

當然,看似簡單的操作過程,其實在不同的環境下,你總會遇到一些意外情況

例1:

D:\軟件工具\SQL SERVER 2008>Setup /QUIET /ACTION=REBUILDDATABASE /INSTANCENAME=M

SSQLSERVER /SQLSYSADMINACCOUNTS=sa /SAPWD=123456 /SQLCOLLATION=SQL_Latin1_General_CP1_CI_AS

Microsoft (R) SQL Server 2008

The following error occurred:

指定的 sa 密碼不滿足強密碼要求。有關強密碼要求的更多信息,請參見安裝程序幫助或 SQL Server 2008 聯機叢書中的“數據庫引擎配置 - 帳戶設置”。

Error result: -2068578304

Result facility code: 1204

Result error code: 0

Please review the summary.txt log for further details

clip_image004

這個需要你修改sa的密碼,滿足強密碼要求就可解決這個問題。

例2: 不小心將/SAPWD中間多了幾個空格,結果報如下錯誤。

image

 

例3:附加數據庫時,沒有用sa賬號,而是用sa創建的windows 身份登錄驗證賬號附加數據庫,結果報如下錯誤,改用sa賬號附加,問題解決

image

 

另外以前也碰到過兩個異常情況,一下子很難重現,以后遇到在補上。

 

clip_image008

另外執行上面腳本時,有可能時間比較長,此時你有沒啥提示,這時千萬不要驚慌,耐心等待,如果你想了解進度,可以通過查看相關日志文件來查看進度,日志信息一般位於C:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Log\ 下,例如C:\Program Files\Microsoft SQL Server\100\Setup Bootstrap\Log\20130909_233902

 

修改數據庫排序規則

更改數據庫排序規則時,需要更改下列內容:

  • 數據庫的默認排序規則,這一新的默認排序規則將應用於數據庫中后續創建的所有列、用戶定義的數據類型、變量和參數。根據數據庫中定義的對象解析 SQL 語句中指定的對象標識符時,也使用新的默認排序規則。
  • 將系統表中的任何 charvarchartextncharnvarchar ntext 列更改為使用新的排序規則。
  • 將存儲過程和用戶定義函數的所有現有 charvarchartextncharnvarchar ntext 參數和標量返回值更改為使用新的排序規則。
  • charvarchartextncharnvarchar ntext 系統數據類型和基於這些系統數據類型的所有用戶定義的數據類型更改為使用新的默認排序規則。

方法1

ALTER DATABASE DataBaseName  COLLATE  Chinese_PRC_CI_AS

此時雖然修改了數據庫的排序規則,但是先前用戶創建的表的排序規則不會改變,仍然是舊的排序規則,你可以用下面SQL腳本驗證。

   1: SELECT c.object_id, c.name, t.name, c.collation_name
   2:  
   3: FROM sys.columns c
   4:  
   5: LEFT JOIN sys.types t on t.system_type_id = c.system_type_id
   6:  
   7: WHERE  object_id=OBJECT_ID('TableName');

這時可能還需要徹底修改這些對象的排序規則,那么可以看看這篇文章Easy way to change collation of all database objects in SQL Server,非常完美的介紹了如和操作。腳本都給你准備OK了。不過,建議做之前做好備份,沒有完美的解決方案,做好了備份,有備無患.

 

有時候如果有其它會話連接到數據庫,你修改數據庫排序規則的時候,會報5030錯,如下所示:

ALTER DATABASE MESDB COLLATE  Chinese_PRC_CI_AS

消息 5030,級別 16,狀態 2,第 1 行

The database could not be exclusively locked to perform the operation.

消息 5072,級別 16,狀態 1,第 1ALTER DATABASE failed. The default collation of database 'MESDB' cannot be set to Chinese_PRC_CI_AS.

Msg 468, Level 16, State 9, Procedure FN_GET_GO_PRE_CUT_DETAIL, Line 69

Cannot resolve the collation conflict between "Chinese_PRC_CI_AS" and "Chinese_PRC_90_CI_AS" in the equal to operation.

 

此時你必須斷開其它會話,通常用下面步驟實現:

修改為單用戶模式

ALTER DATABASE  DataBaseName   SET SINGLE_USER WITH ROLLBACK IMMEDIATE

修改數據庫排序規則

ALTER DATABASE MESDB COLLATE  Chinese_PRC_CI_AS

修改為多用戶模式

ALTER DATABASE DataBaseName SET MULTI_USER

方法2:導出創建數據庫各類對象的腳本,然后替換相應的排序規則,這種方法適合丟棄數據,只保留結構的方式,如果還要考慮數據,那么是個復雜、繁瑣的實現方法。

 

修改列排序規則

 

ALTER TABLE TEST2 ALTER COLUMN NAME CHAR(120)  COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL

 

排序規則沖突

1:SQL 腳本使用臨時表時,出現下面錯誤(服務器排序規則與數據庫排序規則不一致)。

Cannot resolve the collation conflict between "Chinese_PRC_90_CI_AS" and "Chinese_PRC_CI_AS" in the equal to operation.

一般出現這種情況,通常通過顯示指定臨時表相關列的排序規則或在SQL 腳本里面顯示指定排序規則解決。其本質是因為tempdb與用戶數據庫的排序規則不一致導致的。

2:兩台服務器上的數據庫通過鏈接服務器交換操作(或交換數據)時,由於排序規則,有可能導致查詢語句超級慢,出現這個情況,是由於轉換時,導致查詢計划不走索引,走全表掃描所致。

 

參考資料:

http://msdn.microsoft.com/zh-cn/library/ms179254(v=sql.90).aspx

http://blog.csdn.net/feixianxxx/article/details/4633610

http://msdn.microsoft.com/zh-cn/library/ms143508(v=sql.100).aspx

http://msdn.microsoft.com/zh-cn/library/cc281995(v=SQL.100).aspx

http://www.cnblogs.com/JamesLi2015/archive/2013/05/07/3065022.html

http://msdn.microsoft.com/zh-cn/library/cc835499.aspx

http://www.cnblogs.com/blodfox777/archive/2010/01/21/sqlserver-collation-conflict-and-solutions.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM