定序和區分大小寫

資料庫中的文字處理可能相當複雜,而且需要比一個使用者更注意。 一方面,資料庫在處理文字的方式上有很大的差異;例如,雖然某些資料庫預設會區分大小寫(例如 Sqlite、PostgreSQL),但其他資料庫則不區分大小寫(SQL Server、MySQL)。 此外,由於索引使用方式,區分大小寫和類似的層面可能會對查詢效能產生深遠的影響:雖然在區分大小寫的資料庫強制 string.ToLower 不區分大小寫的比較時,這樣做可能會導致應用程式無法使用索引。 此頁面詳細說明如何以有效率的方式設定區分大小寫,或更普遍地設定定序,以及如何以有效率的方式執行此動作,而不會影響查詢效能。

定序簡介

文字處理的基本概念是 定序 ,這是一組規則,決定文字值的順序和比較是否相等。 例如,由於不區分大小寫的定序會忽略大小寫字母之間的差異,以求相等比較,但區分大小寫的定序則不區分大小寫。 不過,由於區分大小寫是區分文化特性的(例如 i ,在 I 土耳其文中代表不同的字母),因此存在多個不區分大小寫的定序,每個定序都有自己的規則集。 定序的範圍也會延伸到區分大小寫,延伸到字元資料的其他層面:例如,在德文中,有時(但不一定)是理想的對待 äae 相同的。 最後,定序也會定義文字值的 排序 方式:而德文位 ä 在 之後 a ,瑞典文會將它放在字母表的結尾。

資料庫中的所有文字作業都會使用定序,無論是明確還是隱含,來判斷作業如何比較和排序字串。 可用的定序及其命名配置的實際清單是資料庫特定的;如需各種資料庫相關檔頁面的連結,請參閱 一節。 幸運的是,資料庫通常會允許在資料庫或資料行層級定義預設定序,並明確指定查詢中特定作業應該使用哪個定序。

資料庫定序

在大部分的資料庫系統中,預設定序是在資料庫層級定義;除非覆寫,否則該定序會隱含地套用至該資料庫內發生的所有文字作業。 資料庫定序通常會在資料庫建立期間設定(透過 CREATE DATABASE DDL 語句),如果未指定,則預設為在設定時間決定的一些伺服器層級值。 例如,SQL Server 中「英文」(美國)電腦地區設定的預設伺服器層級定序是 SQL_Latin1_General_CP1_CI_AS ,這是不區分大小寫、區分腔調的定序。 雖然資料庫系統通常允許改變現有資料庫的定序,但這樣做可能會導致複雜問題:建議您先挑選定序,再建立資料庫。

使用 EF Core 移轉來管理資料庫架構時,模型中的 OnModelCreating 下列方法會將 SQL Server 資料庫設定為使用區分大小寫的定序:

modelBuilder.UseCollation("SQL_Latin1_General_CP1_CS_AS");

資料行定序

您也可以在文字資料行上定義定序,覆寫資料庫預設值。 如果某些資料行不區分大小寫,而資料庫的其餘部分需要區分大小寫,這非常有用。

使用 EF Core 移轉來管理資料庫架構時,下列會將 屬性的資料行 Name 設定為不區分大小寫的資料庫中,否則設定為區分大小寫:

modelBuilder.Entity<Customer>().Property(c => c.Name)
    .UseCollation("SQL_Latin1_General_CP1_CI_AS");

查詢中的明確定序

在某些情況下,不同的查詢必須使用不同的定序來查詢相同的資料行。 例如,一個查詢可能需要對資料行執行區分大小寫的比較,而另一個查詢可能需要在同一個資料行上執行不區分大小寫的比較。 這可以藉由在查詢本身內明確指定定序來完成:

var customers = context.Customers
    .Where(c => EF.Functions.Collate(c.Name, "SQL_Latin1_General_CP1_CS_AS") == "John")
    .ToList();

這會在 SQL 查詢中產生 COLLATE 子句,不論資料行或資料庫層級所定義的定序為何,都會套用區分大小寫的定序:

SELECT [c].[Id], [c].[Name]
FROM [Customers] AS [c]
WHERE [c].[Name] COLLATE SQL_Latin1_General_CP1_CS_AS = N'John'

明確定序和索引

索引是資料庫效能中最重要的因素之一-使用索引有效率執行的查詢,可以在沒有該索引的情況下磨成停止。 索引會隱含繼承其資料行的定序;這表示資料行上的所有查詢都會自動符合使用該資料行上定義的索引的資格,前提是查詢未指定不同的定序。 在查詢中指定明確的定序通常會防止該查詢使用該資料行上定義的索引,因為定序不再相符;因此,建議您在使用這項功能時小心謹慎。 最好是在資料行(或資料庫)層級定義定序,讓所有查詢都隱含地使用該定序並受益于任何索引。

請注意,某些資料庫允許在建立索引時定義定序(例如 PostgreSQL、Sqlite)。 這可讓相同資料行上定義多個索引,以不同的定序加速作業(例如區分大小寫和不區分大小寫的比較)。 如需詳細資訊,請參閱您的資料庫提供者檔。

警告

請務必檢查查詢的查詢計劃,並確定在對大量資料執行的效能關鍵性查詢中使用適當的索引。 透過 EF.Functions.Collate (或呼叫 string.ToLower ) 覆寫查詢中的區分大小寫可能會對應用程式的效能產生非常重大的影響。

內建 .NET 字串作業的轉譯

在 .NET 中,字串相等預設會區分大小寫: s1 == s2 執行序數比較,要求字串相同。 由於資料庫的預設定序會有所不同,而且由於使用索引的簡單相等性是理想的,EF Core 不會嘗試將簡單相等轉譯為資料庫區分大小寫的作業:C# 相等會直接轉譯為 SQL 相等,視使用中的特定資料庫及其定序組態而定,可能會不區分大小寫。

此外,.NET 提供接受 StringComparison 列舉的多 string.Equals 載,以允許指定區分大小寫和比較的文化特性。 根據設計,EF Core 不會將這些多載轉譯為 SQL,而嘗試使用這些多載會導致例外狀況。 有一件事,EF Core 並不知道應該使用哪一個區分大小寫或不區分大小寫的定序。 更重要的是,在大部分情況下,套用定序會防止使用索引,大幅影響非常基本且常用的 .NET 建構的效能。 若要強制查詢使用區分大小寫或不區分大小寫的比較,請透過 上述 詳細 方式明確 EF.Functions.Collate 指定定序。

其他資源

資料庫特定資訊

其他資源