Как исправить проблему с усечением данных для столбцов в табличной переменной с типом данных как varchar (max)

#tsql #sql-server-2014 #dynamic-sql

#tsql #sql-server-2014 #динамический-sql

Вопрос:

У меня есть табличная переменная со столбцом типа varchar(max) . Я сохраняю результирующий набор другого запроса в этой табличной переменной. Длина результата, который я получаю при запросе этой таблицы, равна 7870. Я хотел, чтобы этот результат был перенесен с помощью разделителя через запятую, и перед каждым значением я должен был добавить «t». Но это привело к тому, что данные превысили 8000, поэтому все, что после этого, усекается, даже если тип данных столбца равен varchar(max)

Поскольку тип varchar(max) данных такой, я не хочу, чтобы данные усекались, поэтому попытался установить свойство Set ANSI_WARNINGS OFF перед вставкой данных в табличную переменную, но по-прежнему безуспешно.

 DECLARE @FormattedMainResult VARCHAR(MAX)

DECLARE @CommonColumns TABLE (FinalColumns VARCHAR(MAX)) 

INSERT INTO @CommonColumns
    SELECT main.AllColumnsMain AS CommonColumns
    FROM [dbo].[Staging] Stg
    INNER JOIN [dbo].[Target] main ON Stg.AllColumnsStg = main.AllColumnsMain

SELECT SUM(LEN(FinalColumns)) AS MaxLen_FinalCommonColumns  
FROM @CommonColumns  -- 7870

SELECT * 
FROM @CommonColumns
 

Выходной сигнал:

 Final Columns
---------------
John
Carl
Scott
Rick

SELECT @FormattedMainResult = (SELECT DISTINCT 
                                   STUFF((SELECT ','   't.'  u.FinalColumns
                                          FROM
                                              (SELECT FinalColumns 
                                               FROM @CommonColumns) u
                                          FOR XML PATH('')), 1, 1, '') AS userlist)  

SELECT SUM(LEN(@FormattedMainResult)) AS MaxLen_posttranspose  -- 8230 so data is truncated
PRINT @FormattedMainResult
 

Вывод

 t.John,t.Carl,t.Sc
 

Фактический результат от @FormattedMainResult :

 t.John,t.Carl,t.Sc (data truncated)
 

Ожидаемый результат от @FormattedMainResult :

 t.John,t.Carl,t.Scott,....,t.Rick (no truncation)
 

Обновить

Теперь я сталкиваюсь с проблемой при выполнении инструкции Insert into, которую я получаю из результата запроса select.

Пример,

 Declare @Result nvarchar(max) 
DECLARE @FormattedStgResult varchar(MAX)
DECLARE  @joinCondition VARCHAR(MAX)='s.Id=t.Id'

SET @Result = ''
SET @Result = 'INSERT INTO '   QUOTENAME('vjtest')  '.'  QUOTENAME('dbo')  '.'  QUOTENAME('Staging')  ' ('   @FormattedStgResult   ')  
 SELECT '   @FormattedMainResult   
' FROM '  QUOTENAME('vjtest')  '.'  QUOTENAME('dbo') '.' QUOTENAME('Target')   ' t
 LEFT JOIN '  QUOTENAME('vjtest')  '.' QUOTENAME('dbo') '.' QUOTENAME('Staging')  ' s
 ON '   @joinCondition   
' WHERE s.UniqueId IS NULL'

Exec(@Result)
 

@FormattedMainResult совпадает со старым кодом, который будет иметь значения с префиксом «t». -> t.Id ,t.Name ,1,….,т.Корневой

@FormattedStgResult имеет тот же результат, что и @FormattedMainResult, с той лишь разницей, что нет префикса «t». -> Id, Name, IsDelete, …Rootpid

Это генерирует правильный оператор Insert с ожидаемыми столбцами, но когда он выполняется в Exec(@Result), в нем указывается 0 затронутых строк. Однако, когда тот же запрос, который я выполняю вручную, он показывает 3 затронутых строки.

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

1. Совет: При сборке имен объектов в динамические инструкции SQL рекомендуется использовать QuoteName() , чтобы избежать проблем с нечетными именами, например New Table , с пробелом или зарезервированными словами, такими как From .

2. Поясняю: использование позволяет QuoteName( u.FinalColumns ) избежать неожиданностей при получении имен столбцов из, возможно, ненадежного источника или просто с оригинальными именами столбцов. Применение QuoteName() к 'dbo' не дает большой пользы.

Ответ №1:

Комментарий T-SQL в вашем коде доказывает, что фактическая длина переменной составляет 8230 символов. Проблема в том, что он PRINT ограничен 8000 символами и будет усекать лишние символы.

Используется SELECT @FormattedMainResu< для возврата всего значения, если оно не усечено SSMS в соответствии с максимальной длиной столбца в параметре запроса результатов. Сохраняйте ANSI_WARNINGS ON , если у вас нет устаревшего кода, который требует поведения SQL, отличного от ISO.

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

1. Спасибо, @Dan Guzman с помощью SELECT мои полные данные выводятся в консоль. Однако результатом, который я получу от FormattedMainResult в дальнейшем процессе, будет оператор Insert Into . Итак, эта вставка в Statment теперь печатается в консоли идеально, но когда я выполняю EXEC(FormattedMainResult), она не выдает ошибку, но не выполняет вставку, которую она должна была.

2. @VikasJ, трудно устранить неполадки в коде, который мы не видим. Добавьте соответствующий код, который создает INSERT утверждение, к вашему вопросу.

3. Я добавил код в раздел обновления моего вопроса. Для справки.

4. @VikasJ, добавленный код не присваивает значение @FormattedStgResult so @Result значению с помощью инструкции SQL, NULL и выполнение будет безрезультатным.

5. Можете ли вы, пожалуйста, помочь мне здесь, насколько я понимаю, я присваиваю весь оператор Insert into, который включает в себя другие локальные переменные results FormattedStgResult переменной Result, а затем выполняю полную операцию. Значения в FormattedStgResult и FormattedMainResult уже присвоены. перед вызовом инструкции Insert Into .