#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 .