#sql #sql-server #ntext
#sql #sql-сервер #ntext
Вопрос:
Я пытаюсь вставить данные в таблицу с типом данных столбца as NTEXT
. В идеале он должен хранить более 8000 символов, но в моем случае он сокращает его до 8000 символов.
Я выполняю запрос Insert во время выполнения в процедуре. Ниже приведен пример запроса, который выполняет процедура.
INSERT INTO TMPRESULTS SELECT ('A' ',' 'B' ',' 'C')
A, B, C и т. Д. Являются образцами данных, А фактические данные будут идентифицированы во время выполнения с фактическим содержимым, превышающим 8000 символов. Также переменная, используемая для хранения значения, определяется как « NVARCHAR(MAX)
Однако, когда я пытаюсь выполнить следующий запрос, он вставляет в таблицу более 8000 символов
INSERT INTO TMPRESULTS SELECT ('ABCdddd................')
Я предполагаю, что пока я пытаюсь объединить данные со знаком » «, sql server уменьшает длину до 8000. Я не могу использовать CONCAT
, поскольку данные будут содержать более 256 столбцов / аргументов.
Есть идеи, почему он это делает? Кроме того, если кто-то может помочь с каким-либо альтернативным решением, поскольку мне придется выполнить запрос insert во время выполнения.
Комментарии:
1. Тип выражения задается его членами, а не столбцом / переменной, в которой вы будете хранить результат. Если ни один член выражения не имеет типа
nvarchar(max)
, все выражение не будет повышено доnvarchar(max)
при вычислении, даже если результирующая длина будет больше 4000/8000. Приведите хотя бы один из членов выражения кnvarchar(max)
.2. ПРИВЕТ @GSerg, я сохранил данные в NVARCHAR (MAX), который составляет experssion. Не знаю, должен ли я делать что-нибудь еще
3.
ntext
более десяти лет не рекомендуется. Прошло слишком много времени для ее обновления / замены.
Ответ №1:
Это задокументировано в (Конкатенация строк) (Transact-SQL) — Примечания:
Если результат конкатенации строк превышает ограничение в 8000 байт, результат усекается. Однако, если хотя бы одна из объединенных строк имеет тип большого значения, усечение не происходит.
Для varchar
8000 байт будет 8000 символов, а для nvarchar
4000.
Все ваши литеральные строки в запросе INSERT INTO TMPRESULTS SELECT ('A' ',' 'B' ',' 'C')
представляют собой небольшие типы значений (фактически, все они являются a varchar(1)
). Если вы CONVERT
/ CAST
один из них в a varchar(MAX)
, это решит проблему:
INSERT INTO TMPRESULTS
SELECT (CONVERT(varchar(MAX),'A') ',' 'B' ',' 'C');
если вам нужен an nvarchar
, убедитесь, что вы также объявляете свои литеральные строки как a nvarchar
:
INSERT INTO TMPRESULTS
SELECT (CONVERT(nvarchar(MAX),N'A') N',' N'B' N',' N'C');
Ответ №2:
В SQL Server 2017 года и далее есть функция CONCAT_WS для простого выполнения конкатенации. Вы также можете прочитать о CONCAT
Итак, вместо этого:
INSERT INTO TMPRESULTS SELECT ('A' ',' 'B' ',' 'C')
Мы можем иметь ниже:
INSERT INTO TMPRESULTS SELECT CONCAT_WS(CAST(N',' AS NVARCHAR(MAX)),'A','B','C'))
Ниже я привел пример из SQL Server 2017 для справки:
CREATE TABLE #tempValue(BigValue NVARCHAR(MAX))
INSERT INTO #tempValue
SELECT CONCAT_WS(CAST(N',' AS NVARCHAR(MAX)),REPLICATE('A',4000),REPLICATE('B',4000),REPLICATE('C',4000))
SELECT LEN(BigValue) FROM #tempValue -- 12002
Кроме того, CONCAT_WS лучше по следующим причинам:
Если CONCAT_WS получает аргументы со всеми нулевыми значениями, он вернет пустую строку типа varchar(1).
CONCAT_WS игнорирует нулевые значения во время конкатенации и не добавляет разделитель между нулевыми значениями.
Комментарии:
1. Хотя использование
concat_ws
может выглядеть более чистым, это не имеет ничего общего с проблемой усечения.select cast(CONCAT_WS(',', replicate('A', 4000), replicate('B', 4000), replicate('C', 4000)) as nvarchar(max))
результат все равно будет усечен до 8000 символов.2. @GSerg, спасибо. Я обновил свой ответ. Если один из параметров равен NVARCHAR(MAX), CONCAT_WS автоматически преобразует возвращаемый тип как NVARCHAR(MAX)