はじめに
SQLServerで「照合」という用語をすでに聞いたことがあるはずです。照合は、文字データの並べ替えがどのように行われるかを決定する構成です。これは、SQLServerデータベースエンジンが文字データを処理する際の動作に大きな影響を与える重要な設定です。この記事では、一般的な照合について説明し、照合の処理例をいくつか示します。
照合はどこにありますか?
SQL照合は、サーバー、データベース、および列レベルで見つけることができます。知っておくべきもう1つの重要なことは、照合設定がサーバー、データベース、および列レベルで同じである必要はないということです。また、特定の照合を使用するようにクエリを更新できます。照合が一貫していない場合、予期しない問題が発生する可能性が高いため、この時点で、環境全体で正しい照合を構成することの重要性に気付くでしょう。
利用可能な照合の種類は何ですか?
システム関数sys.fn_helpcollations()
にクエリを実行すると、使用可能な照合の完全なリストを取得できます。select * from sys.fn_helpcollations()
これにより、次の出力が返されます。
言語ごとに特定の照合を探している場合は、名前をさらにフィルタリングできます。たとえば、マオリ語でサポートされている照合を探している場合は、次のクエリを使用できます。
select * from sys.fn_helpcollations() where name like '%Maori%'
これにより、次の出力が返されます。
このようにして、選択した照合に対してサポートされている照合を確認できます。 fn_helpcollations()システム関数をクエリするだけで、合計5508行が返されました。これは、サポートされている照合が多数あることを意味します。これは世界中の言語の大部分をカバーしていることに注意してください。
照合名に表示されるさまざまなオプションは何ですか?
たとえば、次の照合では、Maori_100_CS_AI_KS_WS_SC_UTF8で、照合名にさまざまなオプションが表示されます。
CS –大文字と小文字を区別
AI – アクセントに依存しない
KS –かなタイプセンシティブ
WS –幅に敏感
SC –補足文字
UTF8 –エンコーディング標準
選択した照合オプションのタイプに基づいて、SQL Serverデータベースエンジンは、並べ替えおよび検索操作のための文字データの処理で異なるパフォーマンスを示します。たとえば、SQL照合で大文字と小文字を区別するオプションを使用すると、データベースエンジンは、「Adam」または「adam」を検索するクエリ操作に対して異なる動作をします。 「sample」というテーブルがあり、ユーザー「adam」の名列があるとします。以下のクエリは、名が「Adam」の行がない場合、結果を返しません。これは、照合で「CS-大文字と小文字を区別する」オプションが使用されているためです。
select * from sample where firstname like '%Adam%'
この簡単な例で、正しいSQL照合オプションを選択することの重要性を理解できます。そもそも照合を選択する前に、アプリケーションの要件を理解していることを確認してください。
SQLServerインスタンスでの照合の検索
SQL Server Management Studio(SSMS)でサーバー照合を取得するには、SQLインスタンスを右クリックし、[プロパティ]オプションをクリックして、[全般]タブをオンにします。この照合は、SQLServerのインストール時にデフォルトで選択されています。
または、serverpropertyオプションを使用して照合値を見つけることもできます。
select SERVERPROPERTY('collation'),
SQLデータベースの照合を見つける
SSMSで、SQLデータベースを右クリックし、[プロパティ]に移動します。照合の詳細は、以下に示すように[全般]タブで確認できます。
または、databasepropertyex関数を使用して、データベース照合の詳細を取得することもできます。
select DATABASEPROPERTYEX('Your DB Name','collation')
テーブル内の列の照合を検索する
SSMSで、テーブル、列の順に移動し、最後に個々の列を右クリックして「プロパティ」を表示します。列が文字データ型の場合、照合の詳細が表示されます。
ただし、同時に、文字以外のデータ型の値を確認すると、照合値はnullになります。以下は、intデータ型の列のスクリーンショットです。
または、以下のサンプルクエリを使用して、列の照合値を表示することもできます。
select sc.name, sc.collation_name from sys.columns sc inner join sys.tables t on sc.object_id=t.object_id where t.name='t1' – enter your table name
以下はクエリの出力です。
SQLクエリでさまざまな照合を試す
このセクションでは、クエリでさまざまな照合を使用した場合に、並べ替え順序がどのように影響を受けるかを確認します。以下に示すように、2つの列でサンプルテーブルが作成されます。
fname列には、それが属するデータベースのデフォルトの照合があります。この場合、照合はSQL_Latin1_General_CP1_CI_ASです。
テーブルにいくつかのレコードを挿入するには、以下のクエリを使用します。パラメータに独自の値を割り当てます。
insert into emp values (1,'mohammed') insert into emp values (2,'moinudheen') insert into emp values (3,'Mohammed') insert into emp values (4,'Moinudheen') insert into emp values (5,'MOHAMMED') insert into emp values (6,'MOINUDHEEN')
次に、empテーブルにクエリを実行し、さまざまな照合を使用してfname列で並べ替えます。並べ替えには、列のデフォルトの照合と、大文字と小文字を区別する別の照合(SQL_Latin1_General_CP1_CS_AS)を使用します。
select * from emp order by fname collate SQL_Latin1_General_CP1_CS_AS select * from emp order by fname collate SQL_Latin1_General_CP1_CI_AS – this is default
これらのクエリの出力を以下に示します。使用される照合の違いに注意してください。大文字と小文字を区別せずに大文字と小文字を区別して使用しています。
これらの両方のクエリのクエリプランを確認して、違いを見つけることもできます。列にあるものとは異なる照合を使用する最初のクエリプランでは、追加の「ComputeScalar」演算子に気付くことができます。
「ComputeScalar」演算子の上にマウスを置くと、以下に示すような追加の詳細が表示されます。これは、列で使用されているデフォルトの照合とは異なる照合を使用しているため、暗黙の変換が行われているためです。
この小さな例では、クエリで明示的に照合を使用すると、クエリのパフォーマンスにどのような影響があるかを確認できます。デモデータベースでは、単純なテーブルを使用しましたが、クエリパフォーマンスの小さな変化が予期しない結果を引き起こす可能性があるリアルタイムシナリオを想像してください。
インスタンスレベルで照合を変更できるかどうかを確認する
このセクションでは、デフォルトの照合を変更しなければならない可能性のあるさまざまなシナリオを確認します。サーバーまたはデータベースが引き渡され、それらが標準ポリシーを満たしていない場合があるため、照合を変更する必要がある場合があります。デフォルトのSQLServer照合はSQL_Latin1_General_CP1_CI_ASです。 SQLインスタンスレベルで照合を変更するのは簡単ではありません。これには、ユーザーデータベース内のすべてのオブジェクトのスクリプトを作成し、データをエクスポートし、ユーザーデータベースを削除し、新しい照合でマスターデータベースを再構築し、ユーザーデータベースを作成してから、すべてのデータをインポートする必要があります。したがって、新しいSQLインスタンスをインストールする場合は、最初に照合を正しく行うようにしてください。そうしないと、後で多くの不要な作業を行う必要があります。インスタンスレベルで照合を変更するための段階を詳細に説明することは、各段階に必要な詳細な手順のため、この記事の範囲を超えています。
データベースレベルでの照合の変更
幸い、データベースレベルの照合を変更することは、インスタンスの照合を変更することほど難しくありません。 SSMSとT-SQLの両方を使用して照合を更新できます。 SSMSで、データベースを右クリックし、[プロパティ]に移動して、左側の[オプション]タブをクリックします。そこで、ドロップダウンメニューで照合を変更するオプションを表示できます。
完了したら「OK」をクリックします。データベース照合をSQL_Latin1_General_CP1_CI_ASに変更しました。以下に示すように、操作が失敗するため、データベースが使用されていないときにこの操作を実行することを確認してください。
T-SQLを使用してデータベースの照合を変更するには、続行するクエリを使用します。
USE master; GO ALTER DATABASE mo COLLATE SQL_Latin1_General_CP1_CS_AS; GO
データベースレベルの照合を変更しても、テーブル内の既存の列の照合には影響しないことに気付くでしょう。前の例を使用して、以下のクエリの並べ替え順序に対する照合の影響を確認できます。
select * from emp order by fname collate SQL_Latin1_General_CP1_CS_AS select * from emp order by fname collate SQL_Latin1_General_CP1_CI_AS – - this is default
fname列の照合は元の照合のままであり、データベースレベルの照合を変更した後も変更されません。
ただし、新しいデータベースレベルの照合は、作成する新しいテーブルのすべての新しい列に適用されます。したがって、データベースの照合の変更は、クエリの出力や動作に大きな影響を与えるため、常に徹底的にテストしてください。
列レベルでの照合の変更
前のセクションで、データベースレベルの照合を変更した後でも、テーブル内の既存の列の照合は変更されないことに気づきました。このセクションでは、データベースの照合と一致するように、テーブル内の既存の列の照合を変更する方法を説明します。前のセクションでは、データベース照合をSQL_Latin1_General_CP1_CS_ASに変更しました。次に、このデータベース照合と一致しないユーザーテーブルのすべての列を識別します。このスクリプトを使用して、これらの列を識別できます。
select so.name TableName,sc.name ColumnName, sc.collation_name CollationName from sys.objects so inner join sys.columns sc on so.object_id=sc.object_id where sc.collation_name!='SQL_Latin1_General_CP1_CS_AS' and so.[type] ='U'
デモデータベースからの出力例は次のとおりです。
既存のfname列の照合を「SQL_Latin1_General_CP1_CS_AS」に変更したい場合は、以下のこの変更スクリプトを使用できます。
use mo go ALTER TABLE dbo.emp ALTER COLUMN fname nvarchar(20) COLLATE SQL_Latin1_General_CP1_CS_AS NULL; GO
さまざまな照合を使用してクエリのパフォーマンスを確認した前の例を使用する場合、データベースと同じ照合を使用すると、「スカラーの計算」演算子が使用されないことがわかります。以下のスクリーンショットを参照してください。前の例では、最初の実行プランで「スカラーの計算」演算子が使用されていることに気付いたかもしれません。データベースの照合と一致するように列の照合を変更したため、暗黙的な変換は必要ありません。明示的に異なる照合を使用するため、2番目のクエリに「Computescalar」演算子が表示されます。
select * from emp order by fname collate SQL_Latin1_General_CP1_CS_AS – - this is default select * from emp order by fname collate SQL_Latin1_General_CP1_CI_AS
システムデータベースの照合を変更できますか?
システムデータベースの照合を変更することはできません。システムデータベース(master、model、msdb、tempdb)の照合を変更しようとすると、このエラーメッセージが表示されます。
システムデータベースの照合を変更するには、SQLServerインスタンスレベルでの照合の変更について前述した手順に従う必要があります。このような問題を回避するには、SQLServerを初めてインストールするときに照合を正しく行うことが重要です。
照合の競合に関する既知の問題
発生する可能性のあるもう1つの一般的な問題は、特に一時オブジェクトの使用中の照合の競合に関連するエラーです。一時オブジェクトはtempdbに保存されます。システムデータベースであるtempdbは、SQLインスタンスの照合を想定します。 SQLインスタンス以外の照合機能を持つユーザーデータベースを作成すると、一時オブジェクトを使用するときに問題が発生します。異なる照合を持つテーブルの列を比較しているときにも問題が発生する可能性があります。これで、テーブルレベルで照合を変更できないため、テーブルに異なる照合の列を含めることができることはすでにご存知でしょう。よくあるエラーメッセージは、「equal操作で「Collation1」と「Collation2」の間の照合の競合を解決できません」などです。 Collation1とCollation2は、クエリで使用される任意の照合です。簡単な例を使用して、この照合の競合のデモを作成できます。この記事の前の例を完了している場合は、「emp」という名前のテーブルがすでにあります。デモデータベースに一時テーブルを作成し、提供されているサンプルスクリプトを使用してレコードを挿入するだけです。
create table #emptemp (id int, fname nvarchar(20)) insert into #emptemp select * from emp
両方のテーブルを使用して結合を実行するだけで、以下に示すように、この照合の競合エラーが発生します。
select e.id, et.fname from emp e inner join #emptemp et on e.fname=et.fname
使用されているユーザーデータベースの照合は「SQL_Latin1_General_CP1_CS_AS」であり、サーバーの照合とは一致していません。このタイプのエラーを修正するために、一時オブジェクトで使用される列を変更して、ユーザーデータベースのデフォルトの照合を使用することができます。 「database_default」オプションを使用するか、ユーザーデータベースの照合名を明示的に指定できます。この例では、照合「SQL_Latin1_General_CP1_CS_AS」を使用します。これらのオプションのいずれかを試してください
オプション1: database_defaultオプションを使用する
alter table #emptemp alter column fname nvarchar(20) collate database_default
完了したら、selectステートメントを再度実行すると、エラーが修正されます。
オプション2: ユーザーデータベースの照合を明示的に使用する
alter table #emptemp alter column fname nvarchar(20) collate SQL_Latin1_General_CP1_CS_AS
完了したら、selectステートメントを再度実行すると、エラーが修正されます。
結論
この記事では、次のことを発見しました。
•照合の概念
•利用可能なさまざまな照合オプション
•SQLインスタンス、データベース、および列の照合の詳細の検索
•A SQLクエリで照合オプションを試すための実例
•インスタンスレベル、データベースレベル、および列レベルで照合を変更する
•システムデータベースの照合を変更する方法
•照合の競合とその方法修正するには
これで、照合の重要性と、SQLインスタンスおよびデータベースオブジェクト全体で正しい照合を構成することの重要性について理解できました。上記のオプションのいずれかを実稼働システムに適用する前に、必ずテスト環境でさまざまなシナリオをテストしてください。