Коллажи не обязательно определяются значением по умолчанию для базы данных: они также могут быть установлены в поле строки.
Нет, я никогда не видел пути (и я посмотрел) для выполнения динамических сопоставлений за пределами использования Dynamic SQL для записи предложения COLLATE
в запрос. Или, если число параметров, которые вы должны учитывать довольно минимальны, может возможно попробовать что-то вроде следующего:
SELECT ...
FROM ...
WHERE (@CaseSensitive = 1 AND [Field] LIKE N'%' + @Name + N'%' COLLATE Something_CS_AS)
OR (@CaseSensitive = 0 AND [Field] LIKE N'%' + @Name + N'%')
Кроме того, нет прямой эквивалентность между случаем (или даже Accent, Кана или Ширина) чувствительны и нечувствительны. Хотя большая часть времени есть чувствительные к регистру аналог регистронезависимой сортировки, есть 15 сортировки, которые не чувствителен к регистру только:
;WITH CaseS AS
(
SELECT [name]
FROM sys.fn_helpcollations()
WHERE [name] LIKE N'%[_]cs[_]%'
)
SELECT CaseI.*
FROM sys.fn_helpcollations() CaseI
LEFT JOIN CaseS
ON CaseI.name = REPLACE(CaseS.[name], N'_CS_', N'_CI_')
WHERE CaseI.[name] LIKE N'%[_]ci[_]%'
AND CaseS.[name] IS NULL;
Возвращает:
name description
SQL_1xCompat_CP850_CI_AS ...
SQL_AltDiction_CP850_CI_AI ...
SQL_AltDiction_Pref_CP850_CI_AS ...
SQL_Danish_Pref_CP1_CI_AS ...
SQL_Icelandic_Pref_CP1_CI_AS ...
SQL_Latin1_General_CP1_CI_AI ...
SQL_Latin1_General_CP1253_CI_AI ...
SQL_Latin1_General_CP437_CI_AI ...
SQL_Latin1_General_CP850_CI_AI ...
SQL_Latin1_General_Pref_CP1_CI_AS ...
SQL_Latin1_General_Pref_CP437_CI_AS ...
SQL_Latin1_General_Pref_CP850_CI_AS ...
SQL_Scandinavian_Pref_CP850_CI_AS ...
SQL_SwedishPhone_Pref_CP1_CI_AS ...
SQL_SwedishStd_Pref_CP1_CI_AS ...
Фиксирующими такая сортировка в запросе может вызвать проблемы при переносе кода,
Почему? Где вы планируете переносить код? Если в другую СУБД, то вам уже нужно бороться с различиями типов данных, различиями диалектов SQL, различиями в «передовых методах» и т. Д. Так почему же беспокоиться о сопоставлениях? Если вы точно не знаете, что будете мигрировать на другую СУРБД, вы должны сделать свою систему максимально возможной, используя существующую платформу, насколько это возможно, а не существующую в менее оптимальном состоянии из-за используя только функцию с наименьшим комментарием-знаменателем.
или изменение сортировки БД на последнюю дату.
Зачем вам это нужно? Опять же, все строковые поля с явным значением COLLATION не зависят от базы данных по умолчанию.
Если вы ищете строгого Case (и все, включая Accent и т.д.) чувствительность на эквивалентности (мы не говорить о поиске диапазона или сортировки), то вы можете использовать двоичный сопоставление (т.е. одно окончание либо _BIN
, либо _BIN2
). Просто имейте в виду, что двоичные сортировки могут не сортироваться так, как вы могли бы ожидать, поскольку они не являются сортировками на основе словаря, по крайней мере, не с точки зрения единой бинарной сортировки, которая будет вести себя одинаково на всех языках. Они также не делают эквивалентности между языками (т. Е. Приравнивают «а» к «а», имеющему акцент).
С момента первоначального опубликования этого ответа я обнаружил, что приведенный выше параграф является на самом деле плохим советом. Пожалуйста, сделайте не используйте двоичную сортировку, если цель - чувствительность к регистру. Он слишком строгий и во многих случаях не дает точных результатов.
Кроме того, пожалуйста не использование двоичной сортировки, оканчивающиеся всего _BIN
, поскольку они устарели, так как SQL Server 2005 был выпущен и должен использоваться только при необходимости поддерживать обратную совместимость с другой системой также с использованием _BIN
сортировки. Если вам нужна бинарная сортировка, используйте один конец в _BIN2
.
UPDATE
я смог придумать функцию, чтобы получить случай чувствительную версию, если таковая существует, ушедшей в обобщению. Однако эта функция поможет только создать правильный динамический SQL; он не может использоваться inline в запросе, чтобы динамически устанавливать предложение COLLATE (главным образом потому, что это невозможно). Есть два параметра:
@CollationName
- если вы передаете это, вы получите обратно регистрозависимое версию этого, если таковой существует. Параметр @DatabaseName
будет проигнорирован.
@DatabaseName
- если вы не знаете точное сопоставление, оставьте @CollationName
NULL
и передайте его, и он будет искать настройку по умолчанию для этой базы данных.
- Если оба Титулы будут
NULL
то он будет искать параметры сортировки по умолчанию для базы данных, которая существует функция в.
- Если переданная или смотрел вверх сверка уже чувствительно к регистру, то имя будет возвращены
- TO DO (когда у меня есть время): искать сервер по умолчанию параметры сортировки для баз данных, которые не имеют значения по умолчанию (они будут иметь
NULL
как их имя сортировки по умолчанию)
есть две версии функции: сначала это TVF (как быстрее) и Scalar UDF (поскольку с ними иногда легче взаимодействовать).
Таблица-функции:
USE [Test];
SET ANSI_NULLS ON;
IF (OBJECT_ID(N'dbo.GetCaseSensitiveCollation') IS NOT NULL)
BEGIN
DROP FUNCTION dbo.GetCaseSensitiveCollation;
END;
GO
CREATE FUNCTION dbo.GetCaseSensitiveCollation
(
@CollationName sysname,
@DatabaseName sysname
)
RETURNS TABLE
--WITH SCHEMABINDING
-- Cannot schema bind table valued function 'dbo.GetCaseSensitiveCollation'
-- because it references system object 'sys.fn_helpcollations'.
AS RETURN
WITH collation(name) AS
(
SELECT CONVERT(sysname, COALESCE(@CollationName,
DATABASEPROPERTYEX(COALESCE(@DatabaseName, DB_NAME()), 'Collation')))
)
SELECT col.[name]
FROM sys.fn_helpcollations() col
CROSS JOIN collation
WHERE col.[name] = CASE WHEN collation.[name] LIKE N'%[_]CS[_]%'
THEN collation.[name]
ELSE REPLACE(collation.[name], N'_CI_', N'_CS_')
END;
GO
Примеры:
-- Get CS Collation for the specified Collation
SELECT [name] AS [BySpecificCollation]
FROM dbo.GetCaseSensitiveCollation(N'Indic_General_100_CI_AS_KS_WS', NULL);
-- Get CS Collation based on database default for the specified database
SELECT [name] AS [ByDefaultCollationForDB]
FROM dbo.GetCaseSensitiveCollation(NULL, N'msdb');
-- Get CS Collation based on database default for database that the function exists in
SELECT [name] AS [CurrentDB]
FROM Test.dbo.GetCaseSensitiveCollation(NULL, NULL);
-- Get CS Collation based on database default for the current database
USE [ReportServer];
SELECT [name] AS [CurrentDB]
FROM Test.dbo.GetCaseSensitiveCollation(NULL, DB_NAME());
Скалярное User-Defined Function:
USE [Test];
SET ANSI_NULLS ON;
IF (OBJECT_ID(N'dbo.GetCaseSensitiveCollation2') IS NOT NULL)
BEGIN
DROP FUNCTION dbo.GetCaseSensitiveCollation2;
END;
GO
CREATE FUNCTION dbo.GetCaseSensitiveCollation2
(
@CollationName sysname,
@DatabaseName sysname
)
RETURNS sysname
--WITH SCHEMABINDING
-- Cannot schema bind table valued function 'dbo.GetCaseSensitiveCollation2'
-- because it references system object 'sys.fn_helpcollations'.
AS
BEGIN
DECLARE @NewCollationName sysname;
;WITH collation(name) AS
(
SELECT CONVERT(sysname, COALESCE(@CollationName,
DATABASEPROPERTYEX(COALESCE(@DatabaseName, DB_NAME()), 'Collation')))
)
SELECT @NewCollationName = col.[name]
FROM sys.fn_helpcollations() col
CROSS JOIN collation
WHERE col.[name] = CASE WHEN collation.[name] LIKE N'%[_]CS[_]%'
THEN collation.[name]
ELSE REPLACE(collation.[name], N'_CI_', N'_CS_')
END;
RETURN @NewCollationName;
END;
GO
Примеры:
/* Get CS Collation for the specified Collation */
SELECT dbo.GetCaseSensitiveCollation2(N'Indic_General_100_CI_AS_KS_WS', NULL)
AS [BySpecificCollation];
-- Indic_General_100_CS_AS_KS_WS
/* Get CS Collation based on database default for the specified database */
SELECT dbo.GetCaseSensitiveCollation2(NULL, N'msdb') AS [ByDefaultCollationForDB];
-- SQL_Latin1_General_CP1_CS_AS
/* Get CS Collation based on database default for the current database */
USE [ReportServer];
SELECT Test.dbo.GetCaseSensitiveCollation2(NULL, DB_NAME()) AS [CurrentDB];
-- Latin1_General_CS_AS_KS_WS
/* Get CS Collation based on database default for database where the function exists */
SELECT Test.dbo.GetCaseSensitiveCollation2(NULL, NULL) AS [DBthatFunctionExistsIn];
-- SQL_Latin1_General_CP1_CS_AS
У нас есть большое количество устаревших клиентских баз данных с одинаковой структурой, но с разными сопоставлениями. Некоторые из них нечувствительны к регистру. Было бы здорово, если бы не пришлось адаптировать SP к каждому из них. Если этого не сделать, нам, возможно, придется динамически строить и выполнять запросы. Или, скорее, есть сценарии, которые генерируют варианты SP. Я просто надеялся, что есть более элегантное решение :) – Oxians
@Oxians Я вижу, что вы уже приняли (спасибо), но я добавил предложение к вершине, связанному с «динамическими» запросами. Убедитесь, что вы проверили несколько случаев, хотя этот шаблон обычно не тарифицируется, а также Dynamic SQL. –
@Oxians Я нашел способ получить регистрационную форму (если таковая существует) конкретной сортировки. Посмотрите раздел UPDATE моего ответа :). –