У меня есть 3 переменные:
declare @A NVARCHAR(MAX), @B NVARCHAR(MAX), @C NVARCHAR(MAX)
@A заполнен 40000 символами, а @B заполнен 50000.
Теперь я хочу объединить @a и @b в @c следующим образом:
@c = @a + @b
И обновите колонку с @c. Но когда я их объединяю, я теряю часть данных.
Как я могу это исправить?
Вы пробовали использовать CONCAT вместо +?
Вы теряете данные при вставке или объединении? Можете ли вы воспроизвести ошибку, указав LEN () всех трех переменных?
Я пробую CONCAT, но теряю данные в concatatio
Возможно, у вас проблемы с отображением. Этот может помочь.
@ A30 Не могли бы вы взглянуть на мой ответ? Вероятно, это не конкат. Как вы на самом деле заполняете переменные?
Я действительно могу это воспроизвести. DECLARE @a nvarchar(MAX) = REPLICATE('@',40000); DECLARE @b nvarchar(MAX) = REPLICATE('@',50000); DECLARE @c nvarchar(MAX) = CONCAT(@A,@B); SELECT LEN(@C); возвращает 16000. Это означает, что @a и @b усекаются, а не @c.
это было полезно


Проблема, похоже, не в самой конкатенации.
Вы можете проверить это с помощью этого фрагмента SQL:
declare @A NVARCHAR(MAX), @B NVARCHAR(MAX), @C NVARCHAR(MAX);
set @A = replicate(N'A',4000);
set @A = @A + @A + @A + @A + @A;
set @A = @A + @A;
set @B = replicate(N'B',2500);
set @B = @B + @B + @B + @B + @B;
set @B = @B + @B;
set @B = @B + @B;
-- CONCAT(@A,@B) gives the same result as @A+@B.
-- But @A+@B would return NULL if @A or @B is NULL.
set @C = CONCAT(@A, @B);
select len(@A) as sizeA, len(@B) as sizeB, len(@C) as sizeC;
Возврат:
sizeA sizeB sizeC
----- ----- -----
40000 50000 90000
И NVARCHAR (MAX) может содержать до 2 ^ 30-1 символов.
Так что 1073741823 символов - это ... много. Ссылка здесь
И даже если это ограничено максимальным размером хранилища 2 гигабайта. Тогда он все еще может содержать 1000000000 2-байтовых символов Юникода.
Другими словами, около 3333,3 книг, каждая из которых содержит в среднем 300000 знаков.
Многие библиотеки, вероятно, могли бы хранить все свои романы в одном NVARCHAR (MAX).
Проблема может быть вызвана заполнением @A и / или @B.
Например, если вы используете REPLICATE.
Он может заполнить NVARCHAR только до 4000 символов.
Пример:
declare @X NVARCHAR(MAX);
set @X = replicate(N'X',10000);
select len(@X) as sizeX;
Возврат:
sizeX
-----
4000
Итак, один вопрос, который нужно задать:
How were @A and/or @B filled up, and is the length of their data as expected?
А если @A или @B действительно содержат ожидаемое количество символов?
Но скопировать и вставить ячейку в текстовый редактор не все символы?
Оказывается, из ячейки с данными в формате, отличном от XML, в буфер обмена можно скопировать не более 43679 символов.
И есть также этот предел для данных Non-Xml в OPTIONS SSMS.
Смотрите скриншот ниже.
Так что попытка скопировать и вставить 90000 символов все равно будет усечена.
Одним из обходных путей может быть приведение NVARCHAR (MAX) к типу XML в выбранном элементе. Поскольку XML имеет ограничение по умолчанию в 2 МБ.
Пример фрагмента:
declare @X NVARCHAR(MAX);
set @X = replicate(N'0123456789',333); -- 3330
set @X = @X + @X + @X + @X + @X; -- 16650
set @X = @X + @X + @X + @X; -- 66600
select len(@X) as sizeX, cast(N'<X><![CDATA['+ @X +N']]></X>' as XML) as XasXml;
Хорошая уловка, я (по глупости) предполагал, что REPLICATE будет жаловаться, если у него будет значение больше, чем он может обработать, однако это «особенность» documentrd: ПОВТОР (Transact-SQL)
@Larnu Вы правы. Хорошая находка этой .. "особенности". 8000 символов - это когда вы используете VARCHAR. Так как тогда это 1 байт на символ. С NVARCHAR это меньше: 4000 символов, если у вас есть только 2-байтовые символы Unicode. Я надеюсь, что ОП проливает свет на то, как он заполнял свои переменные. Может быть, у источника его проблемы есть простое решение.
Не удается вставить более 43679 символов в одну ячейку SQL-сервера?
это было полезно
Выясните, что мои данные сохранены полностью, но SSMS - не может вставить более 43679 символов из столбца в режиме сетки
Вместо того, чтобы просто размещать ссылку, включите в свой ответ соответствующие части сообщения. Только ссылка Андерс не одобряет SO, как будто ссылка когда-нибудь станет мертвой, так же как и ваш ответ; и тогда это никому не помогает. Спасибо.
Поделитесь кодом / tsql, с которым у вас возникли проблемы, чтобы мы смогли помочь.