web-dev-qa-db-ja.com

SQL Server:リソースデータベースの照合順序

stopwords を使用して、一部の単語がフルテキストインデクサーによってスキップされるようにしています。テーブルにストップワードを追加できますsys.fulltext_stopwords

SQL Server 2012で stopwords および system-stopwords のリストを取得しようとすると、エラーが発生しました。次の(simplified)クエリを実行しています:

SELECT sys.fulltext_stopwords.stopword 
FROM sys.fulltext_stopwords     

UNION 

SELECT sys.fulltext_system_stopwords.stopword 
FROM sys.fulltext_system_stopwords;

私が得るエラーメッセージは:

"UNION操作での" Latin1_General_CI_AS "と" Latin1_General_BIN "間の照合の競合を解決できません。"

私のクエリの最初のSELECTステートメントのデータベース collat​​ionLatin1_General_CI_ASです。同じことが mastermodelmsdb および tempdb データベースにも当てはまります。

Latin1_General_BINcollat​​ion はどこから来たのですか? sys.fulltext_system_stopwordsテーブルの照合順序が異なるようですが、なぜですか?

[〜#〜]編集[〜#〜]

次のように、クエリで [〜#〜] collat​​e [〜#〜] を使用してエラーを「解決」できます。

SELECT  sys.fulltext_stopwords.stopword COLLATE DATABASE_DEFAULT
FROM sys.fulltext_stopwords 

UNION 

SELECT sys.fulltext_system_stopwords.stopword COLLATE DATABASE_DEFAULT
FROM sys.fulltext_system_stopwords 

System-stopwordsが resource database に格納されていることがわかります。これは、照合順序の違いを説明しています。次の質問は次のようになります。なぜリソースデータベースからの照合がデフォルトと異なるのですか?

5

クエリの最初のSELECTステートメントのデータベース照合順序はLatin1_General_CI_ASです。

まあ、そうではありません。このステートメントにはいくつかの問題があります。

  1. データベースのデフォルトの照合は、文字列リテラル、変数、およびUDFからの戻り値を使用する場合にのみクエリで重要です。さらに、そのデフォルトの照合順序は、列またはCOLLATEキーワードが使用されていない場合にのみ重要です。

  2. SELECTステートメント/クエリは、全体として、照合順序を使用しません。照合順序は文字列フィールドごとに割り当てられ、クエリのフィールドごとに異なる場合があります。

  3. 最初の/最上位クエリの列stopwordは、Latin1_General_CI_AS照合順序を使用していません(これについては後で詳しく説明します)。

システムストップワードがリソースデータベースに格納されていることがわかります。これにより、照合順序の違いを説明できます。

異なるデータベースからの列(または式)は、必ずしも照合順序の違いを説明しません。上記のように、照合は、フィールドがテーブルの列からのものであるか式であるかに関係なく、クエリの各フィールドごとに設定されます。照合順序は通常、照合順序の優先順位から自然に派生します。列の照合順序はリテラルと変数をオーバーライドし、COLLATEキーワードは両方をオーバーライドします。競合がある場合、COLLATEキーワードが必要です。

ただし、ここでの主なポイントは、sys.fulltext_system_stopwordsstopword列がリソースデータベースのテーブルの列にある場合(つまり、mssqlsystemresource)、OR COLLATEキーワードを介して照合順序が設定されているリソースデータベースのビューの式に由来する場合、リソースデータベースのデフォルトの照合順序は関係ありません。

クエリでCOLLATEを使用してエラーを「解決」できます

はい、COLLATEキーワードを使用する方法です。ただし、この競合を修正するには、1つのクエリでCOLLATEキーワードを指定するだけで済みますが、どのクエリでもかまいません。

たとえば、COLLATEキーワードなしでクエリを実行すると、次のようになります。

SELECT ftsw.stopword
FROM sys.fulltext_stopwords ftsw

UNION

SELECT ftssw.stopword
FROM sys.fulltext_system_stopwords ftssw;

メッセージ468、レベル16、状態9、行4
UNION操作での「SQL_Latin1_General_CP1_CI_AS」と「Latin1_General_BIN」の照合の競合を解決できません。

したがって、競合が2番目(つまり、一番下)のSELECTステートメントにあると想定すると、現在のDBのデフォルトの照合順序を適用することで修正できます。

SELECT ftsw.stopword
FROM sys.fulltext_stopwords ftsw
UNION
SELECT ftssw.stopword COLLATE SQL_Latin1_General_CP1_CI_AS
FROM sys.fulltext_system_stopwords ftssw;

そしてそれはうまくいきます。しかし、最初の/最上位のSELECTにCOLLATEを配置するとどうなるでしょうか。

SELECT ftsw.stopword COLLATE SQL_Latin1_General_CP1_CI_AS
FROM sys.fulltext_stopwords ftsw
UNION
SELECT ftssw.stopword
FROM sys.fulltext_system_stopwords ftssw;

それも機能します。そして実際には、次の両方も機能します。

SELECT ftsw.stopword COLLATE Hebrew_100_CI_AS
FROM sys.fulltext_stopwords ftsw
UNION
SELECT ftssw.stopword
FROM sys.fulltext_system_stopwords ftssw;

-- and:

SELECT ftsw.stopword
FROM sys.fulltext_stopwords ftsw
UNION
SELECT ftssw.stopword COLLATE Hebrew_100_CI_AS
FROM sys.fulltext_system_stopwords ftssw;

また、ここではLatin1_General_CI_ASに相当するDATABASE_DEFAULTオプションを使用するのではなく、Latin1_General_BINを使用します(または、さらに良い方法はLatin1_General_100_BIN2です)。 、これはより新しく、より優れています)この特定のケースでは、「異なる」動作を介して同じ文字列に正規化できるさまざまな文字列が保証されます。 UNIONALLなし)とLatin1_General_CI_AS照合順序の大文字と小文字を区別しないので、照合は別の行として表示されます。

Latin1_General_BIN照合はどこから来たのですか? sys.fulltext_system_stopwordsテーブルの照合順序が異なるようですが、なぜですか?

その照合は、ありそうもないソースからのものです。クエリのシステムカタログビューを見てみましょう。

EXEC sys.sp_help N'sys.fulltext_stopwords';

結果は、これがビュー(予想どおり)であり、stopword列の照合順序がLatin1_General_BIN(予想外)であることを示しています。 Latin1_General_BIN照合順序がsys.fulltext_stopwordsからのものである場合、sys.fulltext_system_stopwordsについてはどうですか。また、他の照合順序はどこから来るのでしょうか。見てみよう:

EXEC sys.sp_help N'sys.fulltext_system_stopwords';

結果は、これがビュー(予想どおり)であり、stopword列の照合順序がSQL_Latin1_General_CP1_CI_AS(予想外)であることを示しています。

ここで、これらの各システムカタログビューの定義についてもう少し詳しく説明します。

EXEC sys.sp_helptext N'sys.fulltext_stopwords';

返品(簡略化):

SELECT 
    fts.stopword,
FROM sys.sysftstops fts

その後:

EXEC sys.sp_help N'sys.sysftstops';

結果は、これがシステムテーブルであり、stopword列が実際に照合順序Latin1_General_BINを持っていることを示しています。

次に、他のシステムカタログビューに移動できます。

EXEC sys.sp_helptext N'sys.fulltext_system_stopwords';

返品(簡略化):

SELECT convert(nvarchar(64), stopword) as stopword, language_id
FROM OpenRowset(TABLE FTSYSSTPWD) 

FTSYSSTPWDはリソースデータベースから取得されているため、現時点でできることはこれ以上ありません。

それでも、リソースデータベースからのデータの照合順序を明確にするために最後にできることが1つあります-sys.fulltext_system_stopwords.stopword

CREATE DATABASE [FullTextCollationTest] COLLATE SQL_EBCDIC277_CP1_CS_AS;
GO
USE [FullTextCollationTest];

EXEC sys.sp_help N'sys.fulltext_stopwords';
-- Collation for [stopword] column: Latin1_General_BIN      (same as before)

EXEC sys.sp_help N'sys.fulltext_system_stopwords';
-- Collation for [stopword] column: SQL_EBCDIC277_CP1_CS_AS (same as DB's default Collation)

GO
USE [master];
DROP DATABASE [FullTextCollationTest];
6
Solomon Rutzky