簡體   English   中英

SQL服務器在where表達式中忽略大小寫

[英]SQL server ignore case in a where expression

如何構造SQL查詢(MS SQL Server),其中“where”子句不區分大小寫?

SELECT * FROM myTable WHERE myField = 'sOmeVal'

我希望結果無視案例回來

在SQL Server數據庫的默認配置,字符串比較區分大小寫。 如果您的數據庫覆蓋此設置(通過使用備用排序規則),則您需要指定要在查詢中使用的排序規則類型。

SELECT * FROM myTable WHERE myField = 'sOmeVal' COLLATE SQL_Latin1_General_CP1_CI_AS

請注意,我提供的排序規則只是一個例子(雖然它很可能對你來說很好)。 可以在此處找到有關SQL Server排序規則的更全面的概述。

通常,字符串比較不區分大小寫。 如果您的數據庫配置為區分大小寫的排序規則,則需要強制使用不區分大小寫的排序規則:

SELECT balance FROM people WHERE email = 'billg@microsoft.com'
  COLLATE SQL_Latin1_General_CP1_CI_AS 

我在其他地方找到了其他解 就是說,要用

upper(@yourString)

但是這里的每個人都說,在SQL Server中,它並不重要,因為它無論如何都忽略了案例? 我很確定我們的數據庫區分大小寫。

不,只使用LIKE不起作用。 LIKE搜索與您給定模式完全匹配的值。 在這種情況下, LIKE只會找到文本'sOmeVal'而不是'someval'。

一個可用的解決方案是使用LCASE()函數。 LCASE('sOmeVal')獲取文本的小寫字符串:'someval'。 如果您在比較的兩側使用此功能,它的工作原理如下:

SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')

該語句比較了兩個小寫字符串,因此你的'sOmeVal'將匹配'someval'的所有其他符號(例如'Someval','sOMEVAl'等)。

前2個答案(來自Adam RobinsonAndrejs Cainikovs )有點,有點正確,因為它們在技術上有效,但是他們的解釋是錯誤的,因此在許多情況下可能會產生誤導。 例如,雖然SQL_Latin1_General_CP1_CI_AS排序SQL_Latin1_General_CP1_CI_AS在許多情況下都有效,但不應假設它是適當的不區分大小寫的排序規則。 事實上,鑒於OP在具有區分大小寫(或可能是二進制)的排序規則的數據庫中工作,我們知道OP沒有使用對於這么多安裝(特別是安裝在OS上的任何安裝)的默認排序規則使用美國英語作為語言): SQL_Latin1_General_CP1_CI_AS 當然,OP 可能正在使用SQL_Latin1_General_CP1_CS_AS ,但在處理VARCHAR數據時,重要的是不要更改代碼頁,因為它可能導致數據丟失,並且由排序規則的區域設置/文化控制(即Latin1_General vs French vs希伯來語等)。 請參閱下面的第9點。

其他四個答案在不同程度上都是錯誤的。

我將澄清所有誤解,以便讀者能夠做出最合適/最有效的選擇。

  1. 不要使用UPPER() 這完全是不必要的額外工作。 使用COLLATE子句。 在任何一種情況下都需要進行字符串比較,但是使用UPPER()還必須逐個字符地檢查是否存在大寫映射,然后更改它。 你需要雙方都這樣做。 添加COLLATE只是指示處理使用與默認情況下不同的規則集生成排序鍵。 使用COLLATE肯定比使用UPPER()更高效(或“高性能”,如果你喜歡那個詞:),正如在這個測試腳本(在PasteBin上)中所證明的那樣。

    @Ceisc注意到@ Danny的回答:

    在某些語言中,案例轉換不會往返。 即LOWER(x)!= LOWER(UPPER(x))。

    土耳其大寫“İ”就是常見的例子。

  2. 不,排序規則不是數據庫范圍的設置,至少在此上下文中不是。 有一個數據庫級別的默認排序規則,它被用作未更改和新創建的列的默認值,這些列未指定COLLATE子句(這可能是此常見誤解的來源),但它不會直接影響查詢,除非您正在將字符串文字和變量與其他字符串文字和變量進行比較,或者您正在引用數據庫級元數據。

  3. 不,每個查詢都不是排序規則。

  4. 排序是每個謂詞 (即某些操作數的東西)或表達式,而不是每個查詢。 這對於整個查詢都是如此,而不僅僅是WHERE子句。 這包括JOIN,GROUP BY,ORDER BY,PARTITION BY等。

  5. 不,不要轉換為VARBINARY (例如convert(varbinary, myField) = convert(varbinary, 'sOmeVal') ),原因如下:

    1. 這是一個二進制比較,它不是不區分大小寫的(這個問題要求的是這個)
    2. 如果您確實需要二進制比較,請使用二進制排序規則。 用一個結尾_BIN2如果您使用的是SQL Server 2008或更新,否則你沒有選擇,只能使用一個結尾_BIN 如果數據是NVARCHAR則使用哪個區域設置並不重要,因為在這種情況下它們都是相同的,因此Latin1_General_100_BIN2始終有效。 如果數據是VARCHAR ,則必須使用數據當前所在的相同語言環境(例如Latin1_GeneralFrenchJapanese_XJIS等),因為語言環境決定了所使用的代碼頁,更改代碼頁可以改變數據(即數據)失利)。
    3. 使用可變長度數據類型而不指定大小將依賴於默認大小,並且根據使用數據類型的上下文,有兩種不同的默認值。 字符串類型為1或30。 CONVERT()使用時,它將使用30默認值。 危險的是,如果字符串可能超過30個字節,它將被靜默截斷,並且您可能會從此謂詞獲得不正確的結果。
    4. 即使您需要區分大小寫的比較, 二進制排序規則也不區分大小寫 (另一種非常常見的誤解)。
  6. 不, LIKE並不總是區分大小寫。 它使用要引用的列的排序規則,或者將變量與字符串文字進行比較時使用數據庫的排序規則,或使用可選的COLLATE子句指定的排序COLLATE

  7. LCASE不是SQL Server功能。 它似乎是Oracle或MySQL。 或者可能是Visual Basic?

  8. 由於問題的上下文是將列與字符串文字進行比較,因此實例的排序規則(通常稱為“服務器”)和數據庫的排序規則都不會產生任何直接影響。 每列都存儲排序規則,每列可以具有不同的排序規則,並且這些排序規則不需要與數據庫的默認排序規則或實例的排序規則相同。 當然,如果在創建數據庫時未指定COLLATE子句,則實例排序規則是新創建的數據庫將用作其默認排序規則的默認值。 同樣,如果未指定COLLATE子句,則數據庫的默認排序規則是更改或新創建的列將使用的排序規則。

  9. 您應該使用不區分大小寫的排序規則,否則該排序規則與列的排序規則相同。 使用以下查詢查找列的排序規則(更改表的名稱和模式名稱):

     SELECT col.* FROM sys.columns col WHERE col.[object_id] = OBJECT_ID(N'dbo.TableName') AND col.[collation_name] IS NOT NULL; 

    然后,只需改變_CS_CI 因此, Latin1_General_100_CS_AS將成為Latin1_General_100_CI_AS

    如果列使用二進制排序規則(以_BIN_BIN2 ),則使用以下查詢查找類似的排序規則:

     SELECT * FROM sys.fn_helpcollations() col WHERE col.[name] LIKE N'{CurrentCollationMinus"_BIN"}[_]CI[_]%'; 

    例如,假設該列使用Japanese_XJIS_100_BIN2 ,請執行以下操作:

     SELECT * FROM sys.fn_helpcollations() col WHERE col.[name] LIKE N'Japanese_XJIS_100[_]CI[_]%'; 

有關排序規則,編碼等的更多信息,請訪問: 排序信息

你可以強制區分大小寫,像這樣強制轉換為varbinary:

SELECT * FROM myTable 
WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')

你在哪個數據庫? 使用MS SQL Server,它是一個數據庫范圍的設置,或者您可以使用COLLATE關鍵字覆蓋每個查詢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM