SQL Server nvarchar N префикс для полей varchar - PullRequest
2 голосов
/ 09 октября 2011

Я использую базу данных SQL Server 2005/2008 Express.Есть ли проблемы с использованием префикса N строки (используется для полей nvarchar) для полей varchar?

например, если у меня есть поле базы данных:

CREATE TABLE [dbo].[posts](
    post_title varchar(30)
)

А затем я вставляю только данные asciiно с префиксом N:

INSERT INTO [dbo].[posts] ([post_title]) VALUES (N'My Title');

Проблема возникает из-за того, что я хочу сохранить символы UTF-8 из приложения PHP и в настоящее время не могу определить, является ли поле, в которое оно сохраняется, varchar или nvarchar,Поэтому я просто хочу предположить, что все они nvarchar, учитывая, что я буду когда-либо пытаться сохранять символы ASCII в полях varchar.

Ответы [ 2 ]

2 голосов
/ 27 сентября 2015

Принятый ответ вводит в заблуждение, но это отчасти связано с тем, что сам вопрос является неоднозначным (хотя, вероятно, не преднамеренно).

Да, любая строка Юникода (т. Е. Литерал с префиксом 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
2 голосов
/ 09 октября 2011

Если вы напишите строки с префиксом N в поле varchar, оно будет неявно преобразовано.Других накладных расходов нет, и вы можете смело предположить, что «все - это nvarchar»

Может быть проблема при сравнении переменных nvarchar со столбцами varchar из-за приоритета типа данных.Столбец varchar будет преобразован, и любые индексы не будут использоваться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...