まず第一に、照合、ソート順、コードページなどの用語について人々が話すとき、まだ多くの混乱があると感じているので、このような長い答えをおologiesびします。
BOLから:
SQL Serverの照合順序は、データの並べ替え規則、大文字と小文字、およびアクセントの区別のプロパティを提供します。charやvarcharなどの文字データ型で使用される照合順序は、そのデータ型で表現できるコードページと対応する文字を決定します。SQL Serverの新しいインスタンスをインストールするか、データベースのバックアップを復元するか、サーバーをクライアントデータベースに接続するかにかかわらず、作業するデータのロケール要件、並べ替え順序、大文字と小文字の区別を理解することが重要です。 。
これは、データの文字列がどのようにソートおよび比較されるかに関するルールを指定するため、照合が非常に重要であることを意味します。
注:COLLATIONPROPERTYの詳細
では、まず違いを理解しましょう......
T-SQLの下で実行:
SELECT *
FROM::fn_helpcollations()
WHERE NAME IN (
'SQL_Latin1_General_CP1_CI_AS'
,'Latin1_General_CI_AS'
)
GO
SELECT 'SQL_Latin1_General_CP1_CI_AS' AS 'Collation'
,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'CodePage') AS 'CodePage'
,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'LCID') AS 'LCID'
,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'ComparisonStyle') AS 'ComparisonStyle'
,COLLATIONPROPERTY('SQL_Latin1_General_CP1_CI_AS', 'Version') AS 'Version'
UNION ALL
SELECT 'Latin1_General_CI_AS' AS 'Collation'
,COLLATIONPROPERTY('Latin1_General_CI_AS', 'CodePage') AS 'CodePage'
,COLLATIONPROPERTY('Latin1_General_CI_AS', 'LCID') AS 'LCID'
,COLLATIONPROPERTY('Latin1_General_CI_AS', 'ComparisonStyle') AS 'ComparisonStyle'
,COLLATIONPROPERTY('Latin1_General_CI_AS', 'Version') AS 'Version'
GO
結果は次のようになります。
上記の結果を見ると、唯一の違いは2つの照合順序の並べ替え順序ですが、それは真実ではありません。その理由は次のとおりです。
テスト1:
--Clean up previous query
IF OBJECT_ID('Table_Latin1_General_CI_AS') IS NOT NULL
DROP TABLE Table_Latin1_General_CI_AS;
IF OBJECT_ID('Table_SQL_Latin1_General_CP1_CI_AS') IS NOT NULL
DROP TABLE Table_SQL_Latin1_General_CP1_CI_AS;
-- Create a table using collation Latin1_General_CI_AS
CREATE TABLE Table_Latin1_General_CI_AS (
ID INT IDENTITY(1, 1)
,Comments VARCHAR(50) COLLATE Latin1_General_CI_AS
)
-- add some data to it
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('kin_test1')
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('Kin_Tester1')
-- Create second table using collation SQL_Latin1_General_CP1_CI_AS
CREATE TABLE Table_SQL_Latin1_General_CP1_CI_AS (
ID INT IDENTITY(1, 1)
,Comments VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS
)
-- add some data to it
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('kin_test1')
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('Kin_Tester1')
--Now try to join both tables
SELECT *
FROM Table_Latin1_General_CI_AS LG
INNER JOIN Table_SQL_Latin1_General_CP1_CI_AS SLG ON LG.Comments = SLG.Comments
GO
テスト1の結果:
Msg 468, Level 16, State 9, Line 35
Cannot resolve the collation conflict between "SQL_Latin1_General_CP1_CI_AS" and "Latin1_General_CI_AS" in the equal to operation.
上記の結果から、異なる照合を持つ列の値を直接比較できないことがわかります。 COLLATE
、列の値を比較するするます。
テスト2:
Erland Sommarskogがmsdn に関するこの議論で指摘しているように、大きな違いはパフォーマンスです。
--Clean up previous query
IF OBJECT_ID('Table_Latin1_General_CI_AS') IS NOT NULL
DROP TABLE Table_Latin1_General_CI_AS;
IF OBJECT_ID('Table_SQL_Latin1_General_CP1_CI_AS') IS NOT NULL
DROP TABLE Table_SQL_Latin1_General_CP1_CI_AS;
-- Create a table using collation Latin1_General_CI_AS
CREATE TABLE Table_Latin1_General_CI_AS (
ID INT IDENTITY(1, 1)
,Comments VARCHAR(50) COLLATE Latin1_General_CI_AS
)
-- add some data to it
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('kin_test1')
INSERT INTO Table_Latin1_General_CI_AS (Comments)
VALUES ('kin_tester1')
-- Create second table using collation SQL_Latin1_General_CP1_CI_AS
CREATE TABLE Table_SQL_Latin1_General_CP1_CI_AS (
ID INT IDENTITY(1, 1)
,Comments VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS
)
-- add some data to it
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('kin_test1')
INSERT INTO Table_SQL_Latin1_General_CP1_CI_AS (Comments)
VALUES ('kin_tester1')
---両方のテーブルにインデックスを作成する
CREATE INDEX IX_LG_Comments ON Table_Latin1_General_CI_AS(Comments)
go
CREATE INDEX IX_SLG_Comments ON Table_SQL_Latin1_General_CP1_CI_AS(Comments)
---クエリを実行する
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments = 'kin_test1'
GO
---これには暗黙の変換があります
---クエリを実行する
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = 'kin_test1'
GO
---これには暗黙の変換はありません
暗黙的な変換の理由は、データベース照合とサーバー照合の両方がSQL_Latin1_General_CP1_CI_AS
あり、テーブルTable_Latin1_General_CI_ASに列コメントが定義されVARCHAR(50)
ているためです COLLATE Latin1_General_CI_ASのようにSQL Serverが暗黙の型変換を行う必要があり、ルックアップ中に、。
テスト3:
同じ設定で、varchar列とnvarchar値を比較して、実行プランの変更を確認します。
-クエリを実行する
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_Latin1_General_CI_AS WHERE Comments = (SELECT N'kin_test1' COLLATE Latin1_General_CI_AS)
GO
-クエリを実行する
DBCC FREEPROCCACHE
GO
SELECT Comments FROM Table_SQL_Latin1_General_CP1_CI_AS WHERE Comments = N'kin_test1'
GO
最初のクエリはインデックスシークを実行できますが、暗黙的な変換を実行する必要があることに注意してください。2番目のクエリはインデックススキャンを実行します。
結論:
- 上記のすべてのテストは、データベースサーバーインスタンスにとって正しい照合順序を持つことが非常に重要であることを示しています。
SQL_Latin1_General_CP1_CI_AS
は、ユニコードと非ユニコードのデータをソートできるルールが異なるSQL照合です。
- SQL照合は、nvarcharデータとvarcharデータを比較するときにインデックススキャンを行い、シークしないという上記のテストで見られるように、ユニコードデータと非ユニコードデータを比較するときにインデックスを使用できません。
Latin1_General_CI_AS
は、ユニコードと非ユニコードが同じであるためにデータをソートできるようにするルールを備えたWindows照合です。
- Windows照合では、ユニコードデータと非ユニコードデータを比較するときに、引き続きインデックス(上記の例ではインデックスシーク)を使用できますが、パフォーマンスが若干低下します。
- Erland Sommarskogの回答+彼が指摘した接続項目を読むことを強くお勧めします。
これにより、#tempテーブルで問題が発生することはなくなりますが、落とし穴はありますか?
上記の私の答えをご覧ください。
SQL 2008の「現在の」照合を使用しないことにより、あらゆる種類の機能または機能が失われますか?
それはすべて、参照している機能/機能に依存します。照合とは、データの保存と並べ替えです。
2008年からSQL 2012に移行したとき(2年以内など)はどうですか?問題はありますか?ある時点で、Latin1_General_CI_ASに行くことを強制されますか?
カントバウチ!状況が変化する可能性があり、Microsoftの提案に沿っていることは常に良いことであるため、上記のデータと落とし穴を理解する必要があります。これとこの接続項目も参照してください。
一部のDBAのスクリプトが完全なデータベースの行を完了し、新しい照合を使用してデータベースに挿入スクリプトを実行することを読みました。
照合順序を変更する場合、このようなスクリプトは便利です。サーバーの照合に一致するようにデータベースの照合を何度も変更していることがわかりました。必要な場合はお知らせください。
参考文献: