Все, у меня большой (неизбежный) динамический SQL-запрос. Из-за количества полей в критериях выбора строка, содержащая динамический SQL, превышает 4000 символов. Теперь я понимаю, что существует максимальное значение 4000 NVARCHAR(MAX)
, но глядя на выполненный SQL в Server Profiler для оператора
DELARE @SQL NVARCHAR(MAX);
SET @SQL = 'SomeMassiveString > 4000 chars...';
EXEC(@SQL);
GO
Кажется, работает (!?), для другого запроса, который также является большим, он выдает ошибку, связанную с этим пределом 4000 (!?), он в основном обрезает весь SQL после этого ограничения 4000 и оставляет меня с синтаксической ошибкой. Несмотря на это в профилировщике, он показывает этот динамический SQL-запрос полностью (!?).
Что именно здесь происходит, и должен ли я просто преобразовать эту переменную @SQL в VARCHAR и продолжить?
Спасибо за ваше время.
Пс. Также было бы неплохо иметь возможность распечатать более 4000 символов, чтобы просмотреть эти большие запросы. Следующие ограничены до 4000
SELECT CONVERT(XML, @SQL);
PRINT(@SQL);
есть ли другой крутой способ?
источник
Ответы:
Ваше понимание неверно.
nvarchar(max)
может хранить до (а иногда и больше) 2 ГБ данных (1 миллиард двухбайтовых символов).Из nchar и nvarchar в Книгах онлайн грамматика
Символ
|
означает, что это альтернативы. т.е. вы указываете либоn
буквальное, либо буквальноеmax
.Если вы решите указать конкретное значение,
n
оно должно быть от 1 до 4000, но использованиеmax
определяет его как тип данных большого объекта (заменаntext
которого устарела).Фактически в SQL Server 2008 кажется, что для переменной ограничение в 2 ГБ может быть превышено на неопределенное время при условии наличия достаточного места в
tempdb
( показано здесь )Что касается других частей вашего вопроса
Усечение при объединении зависит от типа данных.
varchar(n) + varchar(n)
будет обрезано до 8000 символов.nvarchar(n) + nvarchar(n)
будет обрезано до 4000 символов.varchar(n) + nvarchar(n)
будет обрезано до 4000 символов.nvarchar
имеет более высокий приоритет, поэтому результатnvarchar(4,000)
[n]varchar(max)
+[n]varchar(max)
не обрезается (для <2 ГБ).varchar(max)
+varchar(n)
не будет усекаться (для <2 ГБ), и результат будет напечатан какvarchar(max)
.varchar(max)
+nvarchar(n)
не будет усекаться (для <2 ГБ), и результат будет напечатан какnvarchar(max)
.nvarchar(max)
+varchar(n)
сначала преобразуетvarchar(n)
ввод,nvarchar(n)
а затем выполнит конкатенацию. Если длинаvarchar(n)
строки превышает 4000 символов, будет выполнено приведениеnvarchar(4000)
и произойдет усечение .Типы данных строковых литералов
Если вы используете
N
префикс и длина строки <= 4000 символов, она будет набрана какnvarchar(n)
гдеn
- длина строки. ТакN'Foo'
будем относитьсяnvarchar(3)
к примеру. Если строка длиннее 4000 символов, она будет рассматриваться какnvarchar(max)
Если вы не используете
N
префикс и длина строки <= 8000 символов, она будет набрана какvarchar(n)
гдеn
- длина строки. Если дольше, какvarchar(max)
В обоих случаях, если длина строки равна нулю,
n
устанавливается значение 1.Новые элементы синтаксиса.
1.
CONCAT
функция здесь не поможетПриведенное выше возвращает 8000 для обоих методов конкатенации.
2. Будьте осторожны с
+=
Возврат
Обратите внимание, что
@A
обнаружено усечение.Как решить возникшую проблему.
Вы получаете усечение либо потому, что вы объединяете два не
max
типа данных вместе, либо потому, что вы объединяетеvarchar(4001 - 8000)
строку сnvarchar
типизированной строкой (дажеnvarchar(max)
).Чтобы избежать второй проблемы, просто убедитесь, что все строковые литералы (или хотя бы те, длина которых находится в диапазоне от 4001 до 8000) имеют префикс
N
.Чтобы избежать первой проблемы, измените назначение с
Чтобы
так что an
NVARCHAR(MAX)
участвует в конкатенации с самого начала (поскольку результат каждой конкатенации такжеNVARCHAR(MAX)
будет распространяться)Избегайте усечения при просмотре
Убедитесь, что у вас выбран режим «результаты в сетку», тогда вы можете использовать
Параметры SSMS позволяют установить неограниченную длину
XML
результатов.processing-instruction
Бит позволяет избежать проблем с символами , такими как<
показ , как<
.источник
nvarchar(4000)
действие. Если строковый литерал меньше 4000 символов, он обрабатывается какnvarchar(x)
. Присоединение к нему другогоnvarchar(x)
значения будет усекать, а не повышать доnvarchar(max)
DECLARE @SQL NVARCHAR(MAX) = ''; SET @SQL = @SQL +
чтобыNVARCHAR(MAX)
в конкатенации участвовал объект .N
префиксом, который будет обрабатываться какnvarchar(max)
без него, он будет обрабатываться какvarchar(n)
неявно приведенный к,nvarchar(4000)
когда вы соединяетесь сnvarchar
Хорошо, поэтому, если позже проблема в том, что у вас есть запрос, превышающий допустимый размер (что может произойти, если он будет продолжать расти), вам придется разбить его на куски и выполнить строковые значения. Итак, допустим, у вас есть хранимая процедура, подобная следующей:
источник
Вы также можете использовать текст nvarchar. это значит, что у вас должна быть просто буква «N» перед массивной строкой, и все! больше нет ограничений
источник
nvarchar(n)
длина строки <= 4000 символов, она будет набрана как где n - длина строки. Так что N'Foo будет рассматриваться, какnvarchar(3)
например. Если строка длиннее 4000 символов, она будет рассматриваться какnvarchar(max)
. Если вы не используете префикс N иvarchar(n)
длина строки <= 8000 символов, она будет набрана как где n - длина строки. Если дольше какvarchar(max)
. Для обоих вышеперечисленных, если длина строки равна нулю, тогда n устанавливается в 1.Принятый ответ помог мне, но я сбился с пути, выполняя конкатенацию varchars, включающих операторы case. Я знаю, что вопрос OP не включает в себя операторы case, но я подумал, что было бы полезно опубликовать здесь для других, подобных мне, которые оказались здесь, пытаясь построить длинные динамические операторы SQL, включающие операторы case.
При использовании операторов case с конкатенацией строк правила, упомянутые в принятом ответе, применяются к каждому разделу оператора case независимо.
источник
источник