OPENROWSET: оператор sp_executesql не работает в @param

Я разрабатываю программу для извлечения файла XML, который WordPress позволяет вам загрузить (по сути, резервную копию).

В этот момент я автоматизировал процесс, чтобы разрешить частое резервное копирование моих данных на SQL Server, и по какой-то причине я застрял на разработке запроса для запуска OPENROWSET, где будет расположен файл XML.

DECLARE @SQL NVARCHAR(MAX)
DECLARE @ParamDefinition NVARCHAR(500) = N'@fstring NVARCHAR(MAX)'
DECLARE @string VARCHAR(MAX) = 
N'C:\[FilePath]\Reviews\thehesperian2016-07-29.xml'

SET @SQL = 
N'INSERT INTO #Temp (Extract_Date, XMLDATA)
SELECT GETDATE()
     , A.*
FROM OPENROWSET(BULK @fstring, SINGLE_BLOB, CODEPAGE = ' + '''RAW''' + ') AS A'

EXEC sp_executesql @SQL
                 , @ParamDefinition
                 , @fstring = @string

Ошибка:

Msg 102, Level 15, State 1, Line 4
Incorrect syntax near '@fstring'.

Я могу превратить это в простой запрос к таблице в предикате, поэтому у меня есть основания подозревать, что именно так читается filepath. Я провел несколько часов, ломая голову, пытаясь понять, почему это неправильно. Хотя я МОГУ использовать QUOTENAME, как в этом например в BULKINSERT, я надеялся встроить все это в динамический SQL (поэтому все еще использую sp_executesql)

Что или почему я делаю неправильно? Любая помощь будет оценена. - С Уважением,

ОТВЕТ

OPENROWSET — MSDN объявляет в собственном абзаце:

OPENROWSET не принимает переменные в качестве аргументов.

QUOTENAME достаточно, хотя я все равно запустил несколько второстепенных REPLACEфункций.


person clifton_h    schedule 29.07.2016    source источник
comment
В вашем динамическом SQL @fstring рассматривается как литерал, а не как переменная.   -  person scsimon    schedule 29.07.2016
comment
@scsimon верно, забыл упомянуть, что я вызывал fstring через параметр proc, поэтому SQL Server не должен догадываться, как я это понимаю.   -  person clifton_h    schedule 30.07.2016
comment
Вам придется использовать Concat с + '''@var''' + для динамического SQL, но вы все еще не уверены, что он находится в OPENROWSET. я не думаю, что это сработает   -  person scsimon    schedule 30.07.2016
comment
@scsimon Я пытался, но, увы, нет способа. Тем не менее, QUOTENAME так же полезен. :) Спасибо за помощь, ваш первый комментарий попал в точку, где я был не прав.   -  person clifton_h    schedule 30.07.2016


Ответы (1)


Путь к файлу данных функции OPENROWSET не допускает параметр. Вместо этого создайте необходимую строку с литералом:

DECLARE @string varchar(MAX) = N'C:\[FilePath]\Reviews\thehesperian2016-07-29.xml';
DECLARE @SQL nvarchar(MAX);
SET @SQL = 
N'INSERT INTO #Temp (Extract_Date, XMLDATA)
SELECT GETDATE()
     , A.*
FROM OPENROWSET(BULK ' + QUOTENAME(@string, '''') + ', SINGLE_BLOB, CODEPAGE = ''RAW'') AS A';
EXEC sp_execute @SQL;

--EXECUTE(@SQL);

ОБНОВЛЕНИЕ:

Добавлен QUOTENAME на случай, если указанный путь к файлу получен из ненадежного источника. Также обратите внимание, что запросы OPENROWSET не параметризуются автоматически. Не имеет значения, выполняется ли здесь запрос с sp_executesql или EXECUTE.

person Dan Guzman    schedule 29.07.2016
comment
Это противоречит точке зрения, которая заключалась в использовании sp_executesql. Кроме того, я ошибся, не упомянув, что @fstring вызывается в процедуре как параметр... так что теоретически SQL-сервер должен иметь возможность обрабатывать его как переменную, верно? - person clifton_h; 30.07.2016
comment
@clifton_h, вы можете использовать sp_executesql @SQL вместо EXEC(@SQL), если это ваше предпочтение, но нет необходимости делать это без параметра. В качестве аргумента имени файла допускается только литеральная строка. OPENROWSET не разрешает параметры, насколько мне известно. - person Dan Guzman; 30.07.2016
comment
Я бы принял ваш ответ, за исключением того, что сначала нужно очистить переменную через QUOTENAME(@string, NCHAR(39) ). во избежание злонамеренного использования. - person clifton_h; 30.07.2016
comment
Хороший момент насчет AdHoc, если только я не использовал его в пакете SSIS (где путь к файлу будет использоваться снова), но это маловероятно. Думаю, я прошел этот раздел в MSDN. Спасибо! - person clifton_h; 30.07.2016