Как я могу избавиться от необходимости префикса запроса WHERE с ‘N’ для строк Unicode?

#sql #sql-server #entity-framework #linq #chinese-locale

#sql #sql-сервер #entity-framework #linq #китайский-locale

Вопрос:

При поиске строки в нашей базе данных, где столбец имеет тип nvarchar, указание префикса ‘N’ в запросе приводит к некоторым результатам. Исключение этого не делает. Я пытаюсь выполнить поиск упрощенной китайской строки в базе данных, которая ранее еще не хранила никаких китайских строк.

Приложение EntityFramework, которое использует базу данных, правильно извлекает строки, и запросы LINQ также работают в приложении. Однако в SQL Server 2014 Management Studio, когда я выполняю SQL-запрос для строки, он не отображается, если я не укажу префикс ‘N’ для unicode. (Даже если столбец имеет тип nvarchar)

Работает:

 var text = from asd in Translations.TranslationStrings
            where asd.Text == "嗄法吖无上几"
            select asd;

            MessageBox.Show(text.FirstOrDefault().Text);
  

Не работает:

 SELECT *
  FROM TranslationStrings
  where Text = '嗄法吖无上几'
  

Если я добавлю в префикс китайских символов ‘N’, это сработает.

Работает:

 SELECT *
  FROM TranslationStrings
  where Text = N'嗄法吖无上几'
  

Пожалуйста, извините за китайские символы, я просто набрал что-то случайное. Мой вопрос в том, могу ли я что-нибудь сделать, чтобы не включать префикс ‘N’ при выполнении запроса?

Большое вам спасибо!

Комментарии:

1. Привет, пожалуйста, поделитесь конфигурацией сортировки экземпляра SQL и версией SQL Server

2. В чем проблема с префиксом, почему вы не хотите его использовать? Это всего лишь второстепенный элемент синтаксиса в виде одинарных кавычек вокруг литерала, я не вижу никакого вреда или особых усилий в его размещении.

3. (N) литералы varchar используют кодовую базу базы данных по умолчанию, если префикс N не используется. Вы можете изменить параметры сортировки базы данных с помощью команды ALTER DATABASE […] COLLATE .

4. 1) Почему вам нужно избавиться от N префикса? 2) Вы передаете строку в качестве параметра или просто объединяете строку? 3) Если вы используете параметры, каков тип данных этого параметра?

5. Не думайте об этом как о каком-то префиксе. Подумайте о N' как о другом виде открывающей кавычки . Вы, предположительно , не задали бы вопрос о том, как вы могли бы опустить открывающие кавычки из строк, не так ли?

Ответ №1:

Как упоминал @sworkalot ниже:

По умолчанию для .Net используется Unicode, поэтому вам не нужно его указывать. Это не относится к Sql Manager.

Если не указано, Sql будет считать, что вы работаете с asci в соответствии с параметрами сортировки, указанными в вашей БД.

Следовательно, при работе с Sql Server вам необходимо использовать N’

https://sqlquantumleap.com/2018/09/28/native-utf-8-support-in-sql-server-2019-savior-false-prophet-or-both/

Ознакомьтесь с этими примерами, обратите пристальное внимание на типы данных и присваиваемые значения:

 DECLARE @Varchar VARCHAR(100) = '嗄'
DECLARE @VarcharWithN VARCHAR(100) = N'嗄' -- Has N prefix

DECLARE @NVarchar NVARCHAR(100) = '嗄'
DECLARE @NVarcharWithN NVARCHAR(100) = N'嗄' -- Has N prefix


SELECT
    Varchar = @Varchar,
    VarcharWithN = @VarcharWithN,
    NVarchar = @NVarchar,
    NVarcharWithN = @NVarcharWithN

SELECT
    Varchar = CONVERT(VARBINARY, @Varchar),
    VarcharWithN = CONVERT(VARBINARY, @VarcharWithN),
    NVarchar = CONVERT(VARBINARY, @NVarchar),
    NVarcharWithN = CONVERT(VARBINARY, @NVarcharWithN)
  

Результаты:

 Varchar VarcharWithN    NVarchar    NVarcharWithN
?       ?               ?           嗄

Varchar VarcharWithN    NVarchar    NVarcharWithN
0x3F    0x3F            0x3F00      0xC455
  

NVARCHAR тип данных хранит 2 байта для каждого символа, в то время как VARCHAR хранит только 1 (вы можете видеть это при VARBINARY приведении ко 2-му SELECT ). Поскольку для хранения представления китайских символов требуется 2 байта, вы должны использовать NVARCHAR для их хранения. Если вы попытаетесь вставить их в a, VARCHAR это будет сохранено как ? , и вы потеряете исходную информацию о символах. Это также происходит в 3-м примере, потому что литерал не имеет N поэтому он преобразуется в VARCHAR перед фактическим присвоением значения переменной.

Именно из-за этого вам нужно добавить N префикс при вводе этих символов в виде литералов, чтобы механизм SQL знал, что вы вводите символы, которым требуется представление в 2 байта. Поэтому, если вы проводите сравнение с NVARCHAR столбцом, всегда добавляйте N префикс. Вы можете изменить параметры сортировки базы данных, но рекомендуется всегда использовать правильный тип данных независимо от параметров сортировки, чтобы у вас не возникало проблем при использовании кодирования в разных базах данных.

Если бы вы могли объяснить причину, по которой вы хотите опустить N префикс, мы могли бы обратиться к этому, хотя я считаю, что в этом конкретном случае нет обходного пути.

Комментарии:

1. Спасибо за ответ! Я искал способ избавиться от этого, чтобы упростить работу для других, которым нужно будет работать с базой данных. В прошлом нам не приходилось этого делать, поэтому с этого момента людям нужно будет помнить об этом. К счастью, большая часть взаимодействия с базой данных происходит через . СЕТЬ, которая будет работать. (Как указано в ответе от srworksalot)

2. @bluiska и EzLo: Привет. Разница между VARCHAR и NVARCHAR заключается в размере «единиц», которые используются в комбинациях для создания символов в определенной кодировке. VARCHAR , 8-разрядный тип, создает символы в комбинациях от 1 до 4 байт, но всегда в 1 байтовых единицах. NVARCHAR , 16-разрядный тип, создает символы в 2 или 4 байтах, но всегда в 2 байтовых единицах. Для получения подробной информации, пожалуйста, прочитайте мой пост: Сколько байт на символ в SQL Server: полностью полное руководство

Ответ №2:

По умолчанию для .Net используется Unicode, поэтому вам не нужно его указывать. Это не относится к Sql Manager.

Если не указано, Sql будет считать, что вы работаете с asci в соответствии с параметрами сортировки, указанными в вашей БД.

Следовательно, при работе с Sql Server вам необходимо использовать N’

https://sqlquantumleap.com/2018/09/28/native-utf-8-support-in-sql-server-2019-savior-false-prophet-or-both/

Комментарии:

1. Большое спасибо! Предполагая, что это ASCII, я мог бы понять, почему это не сработает.