web-dev-qa-db-ja.com

「場所」のアクセントを無視する

私たちのデータベースには、caron/hatschekを持つ複数のエントリがあります。現在、ユーザーは、caron/hatschekを含めずにエントリを検索するときに、エントリを検索したいと考えています。これを簡単な例で示します。

私たちのデータベースにはエントリがあります(名前で連絡してください)

Millière

この名前は、その人が住んでいる国では正しいです。

私たちの国では、caron/hatschekの文字がないため、ユーザーはMilliereを検索します。 èは明らかにeと一致しないため、結果は表示されません。

これがéèêとしてどのように実現されるかはわかりません(さらに、これはeの例にすぎません... )。

(もう1つの方法は、caron/hatschekですべての文字列を基本的な文字列に置き換えるだけなので、はるかに簡単です。明らかに、ユーザーはデータベース内の名前の正しいバージョンを求めています。

18
lumo

この問題は、 アクセントを区別しない照合 を使用して解決できます。

データベースはおそらくAS(Accent Sensitive)照合を使用しているため、デフォルトではアクセントを含む完全一致を検索します。

比較で照合を指定することにより、データベースのデフォルト以外の照合を使用するようにWHERE句に指示できます。

this dbfiddle でLATIN1照合を使用して例を作成しましたが、ASをAIに変更するだけで、使用している照合で同じアプローチを使用できます。列が現在使用している照合。

Colummnが使用している照合に一致するアクセントを区別しない照合を使用します。たとえば、列がSQL_Latin1_General_CP1_CI_ASを使用している場合、SQL_Latin1_General_CP1_CI_AIまたはLatin1_General_CI_ASではなくLatin1_General_100_CI_ASを使用するか、これら2つのバリエーションのいずれかを使用しないでください。ユーザーによって。

現在の照合順序は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句を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 が好むように)。