Sql-Server

忽略“where”子句中的重音符號

  • November 23, 2021

在我們的數據庫中,我們有多個帶有重音、插入符號或carons(又名 hačeks)的條目。這些口音也統稱為變音符號

現在我們的使用者在搜尋不包含這些變音符號的條目時希望找到包含這些變音符號的條目。我將通過一個簡單的例子來展示這一點:

在我們的數據庫中,我們有條目(聯繫人姓名)

Millière

…所以這個名字在這個人居住的國家是正確的。

在我國,我們沒有任何帶有變音符號的字元,因此我們的使用者搜尋Milliere. 沒有結果出來,因為è顯然不匹配e

我不知道這如何實現為é, èê還有更多可用(這只是字母e… 的範例)。

(另一種方法會更容易,因為我可以簡單地將所有字母替換為 caron/haček 與基本字母。顯然,我們的使用者確實希望數據庫中名稱的正確版本,而不是殘缺的。)

這個問題可以使用不區分重音的排序規則來解決。

您的數據庫可能正在使用 AS(Accent Sensitive)排序規則,因此預設情況下它將搜尋包括重音在內的完全匹配。

您可以通過指定帶有比較的排序規則來指示 WHERE 子句使用數據庫預設值之外的其他排序規則。

這個 dbfiddle 中,我使用 LATIN1 排序規則創建了一個範例,但您可以使用與您正在使用的排序規則相同的方法,只需將 AS 更改為 AI 以用於您的列目前使用的排序規則。

使用與列正在使用的排序規則匹配的不區分重音排序規則。例如,如果該列使用SQL_Latin1_General_CP1_CI_AS、 useSQL_Latin1_General_CP1_CI_AI和 notLatin1_General_CI_ASLatin1_General_100_CI_AS這兩者的任何變體,因為非 SQL_ 排序規則的行為將在更多方面有所不同,而不僅僅是對重音不敏感,而這可能不是使用者所期望的。

您可以在 中檢查目前排序規則sys.columns

CREATE TABLE testaccent (name nvarchar(50));
GO
INSERT INTO testaccent (name) VALUES ('Millière') , ('Milliere');
GO
-- returns Miliere
SELECT * FROM testaccent WHERE name = 'Milliere';

-- returns both
SELECT * FROM testaccent WHERE name='Milliere' COLLATE Latin1_General_CI_AI

--only returns Miliere
SELECT * FROM testaccent WHERE name='Milliere' COLLATE Latin1_General_CI_AS

通讀使用 SQL Server 排序規則以獲取更多資訊。

然後再一次,您可能希望排序以使用此排序規則(如評論中的peufeu所述)以確保“é”與“e”排序。否則,按字母順序對結果進行分頁的人會驚訝地發現沒有在他們期望的位置找到“é”,但如果您只想觸摸此查詢,您也可以將COLLATE子句添加到 the 中ORDER BY

正如Solomon Rutzky在評論中指出的那樣,如果這只影響 1 列或幾列,另一種選擇是創建一個非持久計算列,它只是重複“名稱”列並提供不區分重音的排序規則,然后索引計算的柱子。這避免了由於更改查詢中的排序規則而導致的掃描。然後查詢需要過濾新列。

就像是:

ALTER TABLE 
dbo.[table_name] ADD [SearchName] datatype_of_name_column 
AS ([Name] COLLATE LATIN1_GENERAL_100_CI_AI)); 

CREATE INDEX [IX_table_name_SearchName] 
ON dbo.[table_name] ([SearchName] ASC);

或者您也可以創建一個視圖而不是添加一個計算列(如jyao喜歡的那樣)。

引用自:https://dba.stackexchange.com/questions/190969