TSQL Prefixing String Literal on Insert - любое значение для этого или избыточное?

Я просто унаследовал проект, который имеет код, похожий на следующий (довольно простой) пример:

DECLARE @Demo TABLE
(
    Quantity INT,
    Symbol NVARCHAR(10)
)

INSERT INTO @Demo (Quantity, Symbol)
SELECT 127, N'IBM'

Мой интерес к N перед строковым литералом.

Я понимаю, что префикс N должен указывать кодировку (в данном случае Unicode). Но так как выбор только для того, чтобы вставить в поле, которое явно уже Юникод, не будет ли это значение автоматически повышаться?

Я запустил код без N и, похоже, работает, но не хватает ли чего-то, что предполагал предыдущий программист? Или был N надзор над его/ее частью?

Я ожидаю поведение, подобное тому, когда я передаю поле int в decimal (auto-upcast). Могу ли я избавиться от этих N s?

Ответ 1

Ваш тест на самом деле недействителен, попробуйте что-то вроде китайского символа вместо этого, я помню, если вы его не префикс, он не будет вставлять правильный символ

Например, первый показывает знак вопроса, а нижний показывает квадрат

select '作'

select N'作'

Лучший пример, даже здесь вывод не тот же

declare @v nvarchar(50), @v2 nvarchar(50)

select @v = '作', @v2 = N'作'

select @v,@v2

Так как вы выглядите как таблица акций, почему вы используете unicode, есть даже символы, которые являются unicode. Я никогда не видел их, и это включает в себя ISIN, CUSIPS и SEDOLS

Ответ 2

Да, SQL Server автоматически преобразует (расширяет, отменяет) varchar в nvarchar, поэтому вы можете удалить N в этом случае. Конечно, если вы указываете строковый литерал, где символы фактически не присутствуют в настройке по умолчанию для базы данных, вам это нужно.

Это похоже на то, что вы можете суффикс числа с "L" в C и др., чтобы указать его длинный литерал вместо int. Написание N'IBM 'является точной или подчиненной привычкой, в зависимости от вашей точки зрения.

Одна ловушка для неосторожного: nvarchar не автоматически преобразуется в varchar, и это может быть проблемой, если ваше приложение все Unicode, а ваша база данных не является. Например, у нас это было с jTDS JDBC-драйвером, который привязывал все значения параметров как nvarchar, что приводило к таким действиям, как:

select * from purchase where purchase_reference = N'AB1234'

(где purchase_reference - столбец varchar)

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

select * from purchase where CONVERT(NVARCHAR, purchase_reference) = N'AB1234'

и, следовательно, индекс buy_reference не использовался.

В противоположность этому, обратное хорошо: если purchase_reference был nvarchar, а приложение передано в параметре varchar, тогда перезаписанный запрос:

select * from purchase where purchase_reference = CONVERT(NVARCHAR, 'AB1234')

будет хорошо. В конце концов, нам пришлось отключить параметры привязки как Unicode, что вызвало множество проблем i18n, которые считались менее серьезными.