Как устранить эту ошибку функции SQL String_Split

#sql #sql-server

#sql #sql-сервер

Вопрос:

Пытаюсь использовать функцию SQL string_split в динамическом запросе, но я продолжаю получать следующую ошибку. Недопустимое имя столбца «Описание счета». Тип данных аргумента тип void недопустим для аргумента 1 функции string_split. Я не могу разобраться в проблеме. Любая помощь приветствуется.

 DECLARE @AuthFile nvarchar(max); DECLARE @TableName AS SYSNAME;
DECLARE @sql nvarchar(max);

SET @TableName = '__tTransactions_'   REPLACE(CONVERT(CHAR(10), GETDATE(), 103), '/', '');
SET @AuthFile = '__Authorization';

create table #temp (TransactionID nvarchar(1000), CartID int, TotalAmount nvarchar(1000))

SET @sql = 'select [Transaction ID] as TransactionID, cs.value as CartID, [Total Amount] as TotalAmount 
            into #temp 
            from '   @TableName   '
            cross apply string_split([Invoice Description], ''|'') cs
            where (isnull([Invoice Description], '''') <> '''')';

print(@sql);
EXEC(@sql);
SET @sql = '';

select * from #temp

drop table #temp
 

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

1. Я бы посоветовал вам предоставить образцы данных, желаемые результаты и четкое объяснение того, что должен делать код.

2. Разделение строк не работает с некоторыми типами данных, и в результате вам приходится приводить тип данных к тому, что он может использовать. Я предполагаю, что вы используете varchar(max) или какой-либо другой тип данных, который иногда обрабатывается как большой двоичный объект. Сообщите нам, что это за тип данных и исправляет ли его CAST() для varhcar(8000) для вас.

3. Если я извлекаю этот запрос из переменной и запускаю его не как динамический запрос, он работает просто отлично.

4. «тип void» звучит немного странно. Не знаю, почему в нем не указан фактический тип данных. Вы увидите это, если __tTransactions_05042021 вообще не содержит столбца Invoice Description , но также наряду с другими ошибками для Invalid column name 'Invoice Description'

5. В любом случае вы не хотите использовать SELECT ...INTO здесь, поскольку это создаст новую временную таблицу в области динамического SQL, которая будет уничтожена, как только она завершится

Ответ №1:

Можно создать примерную таблицу для запуска вашего динамического sql.

 drop table if exists #__tTransactions_05042021;
create table #__tTransactions_05042021 (
    [Transaction ID] int, 
    [Total Amount] float,
    [Invoice Description] varchar(255)
);
insert #__tTransactions_05042021 values 
    (1, 100, '1|2|3'),
    (2, 200, '4|5|6')
 

Этот пример представляет собой временную таблицу, поэтому я изменил ваш код, чтобы указывать на временную таблицу вместо реальной, но в остальном это то же самое:

 DECLARE @AuthFile nvarchar(max); 
DECLARE @TableName AS SYSNAME;
DECLARE @sql nvarchar(max);

SET @TableName = '#__tTransactions_'   REPLACE(CONVERT(CHAR(10), GETDATE(), 103), '/', '');
SET @AuthFile = '__Authorization';

create table #temp (TransactionID nvarchar(1000), CartID int, TotalAmount nvarchar(1000))

SET @sql = 'select [Transaction ID] as TransactionID, cs.value as CartID, [Total Amount] as TotalAmount 
            into #temp 
            from '   @TableName   '
            cross apply string_split([Invoice Description], ''|'') cs
            where (isnull([Invoice Description], '''') <> '''')';

print(@sql);
EXEC(@sql);
SET @sql = '';

select * from #temp

drop table #temp;
 

Этот код НЕ выдает ошибку. Это не код. Это структура таблицы, на которую вы указываете. Посмотрите, какая таблица предназначена для вашего распечатанного предложения from, и посмотрите на структуру таблицы. Вы должны обнаружить, что в нем нет столбца «описание счета».

Теперь в вашем коде больше проблем. А именно, вы пытаетесь перекачать свои данные в ‘#temp’ внутри динамического sql. Ваш код не завершится ошибкой, но он также не будет работать, потому что контекст отличается между кодом внутри динамического sql и кодом вне его.

Вы захотите либо использовать глобальную временную таблицу (например, ##temp), либо использовать insert-exec . Ниже показано, как вы изменили бы последнюю часть своего кода, чтобы выполнить последнее:

 create table #temp (TransactionID nvarchar(1000), CartID int, TotalAmount nvarchar(1000))

SET @sql = 'select [Transaction ID] as TransactionID, cs.value as CartID, [Total Amount] as TotalAmount 
            from '   @TableName   '
            cross apply string_split([Invoice Description], ''|'') cs
            where (isnull([Invoice Description], '''') <> '''')';

print(@sql);
insert #temp
EXEC(@sql);
SET @sql = '';