Прежде всего, извиняюсь за такой длинный ответ, так как я чувствую, что все еще существует большая путаница, когда люди говорят о таких терминах, как сортировка, порядок сортировки, кодовая страница и т. Д.
От 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
Результаты будут:
Глядя на приведенные выше результаты, единственное различие заключается в порядке сортировки между двумя параметрами сортировки. Но это не так, и вы можете понять, почему, как показано ниже:
Тест 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:
Основное различие заключается в производительности, как указывает Эрланд Соммарског в этом обсуждении 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 должен выполнить преобразование IMPLICIT.
Тест 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
Обратите внимание, что первый запрос может выполнять поиск по индексу, но должен выполнять неявное преобразование, тогда как второй выполняет сканирование индекса, которое оказывается неэффективным с точки зрения производительности, когда он сканирует большие таблицы.
Вывод :
- Все вышеперечисленные тесты показывают, что правильное сопоставление очень важно для вашего экземпляра сервера базы данных.
SQL_Latin1_General_CP1_CI_AS
это SQL сортировка с правилами, которые позволяют сортировать данные для Unicode и Non-Unicode отличаются.
- Параметры сортировки SQL не смогут использовать индекс при сравнении данных в Юникоде и не-Юникоде, как показано в предыдущих тестах, согласно которым при сравнении данных nvarchar с данными varchar выполняется сканирование индекса, а не поиск.
Latin1_General_CI_AS
это сопоставление Windows с правилами, которые позволяют сортировать данные для Unicode и Non-Unicode одинаковы.
- Для сравнения в Windows по-прежнему может использоваться индекс (поиск по индексу в приведенном выше примере) при сравнении данных в Юникоде и не в Юникоде, но вы видите небольшое снижение производительности.
- Настоятельно рекомендую прочитать Erland Sommarskog answer + connect, на которые он указал.
Это позволит мне не иметь проблем с таблицами #temp, но есть ли подводные камни?
Смотрите мой ответ выше.
Потеряю ли я какую-либо функциональность или какие-либо функции, не используя «текущую» сортировку SQL 2008?
Все зависит от того, какие функции / функции вы имеете в виду. Сортировка - это хранение и сортировка данных.
Как насчет того, когда мы перейдем (например, через 2 года) с 2008 на SQL 2012? Будут ли у меня проблемы тогда? Буду ли я в какой-то момент вынужден перейти на Latin1_General_CI_AS?
Не могу ручаться! Поскольку все может измениться, и всегда хорошо быть в соответствии с предложением Microsoft +, вам необходимо понимать свои данные и подводные камни, о которых я упоминал выше. Также обращайтесь к этому и этому пункту.
Я прочитал, что некоторые сценарии DBA завершают строки полных баз данных, а затем запускают сценарий вставки в базу данных с новым сопоставлением - я очень напуган и опасаюсь этого - вы бы порекомендовали это сделать?
Если вы хотите изменить параметры сортировки, тогда такие сценарии полезны. Я обнаружил, что много раз меняю параметры сортировки баз данных, чтобы они соответствовали параметрам сортировки серверов, и у меня есть несколько сценариев, которые делают это довольно аккуратно. Дайте мне знать, если вам это нужно.
Ссылки :