Принятый ответ вводит в заблуждение, но это отчасти связано с тем, что сам вопрос является неоднозначным (хотя, вероятно, не преднамеренно).
Да, любая строка Юникода (т. Е. Литерал с префиксом N
,или переменные с префиксом XML
и N
) неявно преобразуются в 8-битный ASCII при сохранении в поле CHAR
/ VARCHAR
/ TEXT
(не используйте это!). НО , и это может быть довольно важным отличием во многих случаях, только кодовые точки Unicode в диапазоне от U + 0000 до U + 007F (т. Е. Значения ASCII 0 - 127) гарантированно преобразуются правильно.Все, начиная с U + 0080 (т.е. значение ASCII 128) и выше, может преобразовываться или не преобразовываться, в зависимости от кодовой страницы, подразумеваемой сопоставлением вставляемого поля.Если кодовая страница этого сопоставления не имеет сопоставления для этого символа, вместо этого вы получите ?
.
Чтобы выяснить, что именно является кодовой страницей, сначала найдите сопоставление поля с помощьюиз следующих двух запросов:
SELECT * FROM sys.columns WHERE [object_id] = OBJECT_ID(N'table_name');
-- OR:
EXEC sp_help N'table_name';
Затем вы можете найти кодовую страницу из сопоставления, используя:
SELECT COLLATIONPROPERTY('collation_name', 'CodePage');
И затем вы можете найти диаграмму на любом из нескольких сайтов.На основе этого номера кодовой страницы будет показано, что сопоставлено.
И параметры сортировки не для каждой строки, а для каждого поля.Таким образом, независимо от того, для чего используется сопоставление для поля, определяется набор символов для полей, отличных от Юникода (т. Е. CHAR
/ VARCHAR
/ TEXT
).
Поэтому вопрос таков: что подразумевается под термином "ASCII "в вопросе?Технически это относится только к 7-битным значениям (первые 128; значения 0–127), но люди часто используют его для обозначения всего, что может вписаться в один байт, который также включает в себя расширенные значения ASCII (вторые 128; значения128 - 255), которые зависят от кодовой страницы.
Относительно потенциальной проблемы, связанной с наличием столбца VARCHAR
для переменных и литералов NVARCHAR
: индексы не будут игнорироваться, ноесть некоторое негативное влияние, которое зависит от параметров сортировки столбца VARCHAR
.
Если столбец столбца представляет собой SQL Server (то есть столбец, начинающийся с SQL_
, например SQL_Latin1_General_CP1_CI_AS
)), тогда вы можете получить индексное сканирование, но не поиск.
Но, если столбец Collation - это Windows Collation (то есть тот, который не начинается с SQL_
, например Latin1_General_100_CI_AS
),тогда вы можете получить поиск по индексу.
Следующий тест показывает это поведение:
-- DROP TABLE dbo.VarcharColumnIndex;
CREATE TABLE dbo.VarcharColumnIndex
(
ID INT IDENTITY(1, 1) NOT NULL CONSTRAINT [PK_VarcharColumnIndex] PRIMARY KEY CLUSTERED,
SqlServerCollation VARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS,
WindowsCollation VARCHAR(50) COLLATE Latin1_General_100_CI_AS
);
CREATE NONCLUSTERED INDEX [IX_VarcharColumnIndex_SqlServerCollation]
ON dbo.VarcharColumnIndex ([SqlServerCollation]);
CREATE NONCLUSTERED INDEX [IX_VarcharColumnIndex_WindowsCollation]
ON dbo.VarcharColumnIndex ([WindowsCollation]);
INSERT INTO dbo.VarcharColumnIndex ([SqlServerCollation], [WindowsCollation])
VALUES ('a', 'b');
DECLARE @a NVARCHAR(50) = N'a';
SELECT [SqlServerCollation] FROM dbo.VarcharColumnIndex WHERE [SqlServerCollation] = @a;
-- Index Scan
DECLARE @b NVARCHAR(50) = N'b';
SELECT [WindowsCollation] FROM dbo.VarcharColumnIndex WHERE [WindowsCollation] = @b;
-- Index Seek