Ключом к этой проблеме является формулировка сообщения об ошибке (выделено мной):
Идентификатор, начинающийся с
Идентификатор – это имя объекта или элемента в SQL Server, а не литеральная строка. Например, master
, dbo
и xp_cmdshell
— все идентификаторы.
Итак, у вас есть два варианта:
Простое исправление (но не лучшая практика)
Проблема с идентификаторами — это подсказка, указывающая на строку SET QUOTED_IDENTIFIER ON
. Простое изменение ON
на OFF
позволит этому работать. Однако вы получите сообщение об ошибке, если в вашем пути и/или шаблоне имени файла есть пробел (например, C:\Program Files (x86)\ ).
Исправление передового опыта (это все еще довольно просто)
Используйте одинарные кавычки вместо двойных кавычек вокруг команды оболочки. А поскольку вы создаете команду в динамическом SQL, в обоих случаях она должна быть заключена в две одинарные кавычки. Итак, ...xp_cmdshell ''dir ... /b''...
Если в самом пути есть пробелы, то вам нужны двойные кавычки вокруг пути: ...xp_cmdshell ''dir "..." /b''...
Следовательно, полный синтаксис будет таким:
SET @Query ='master.dbo.xp_cmdshell ''dir "'+ @FilePath + '\' + @SourceFiles +'" /b''';
Поместив его в полный исходный код вместе с длинным именем пути и дополнительными SELECT
и PRINT
, чтобы увидеть, что происходит, вы получите:
DECLARE @FilePath varchar(256)='C:\Users\Solomon\AppData\Local\Microsoft\HelpViewer2.0\TableOfContentsFilterCache\VisualStudio11\en-US',--Path with a length more than 128 char
@SourceFiles varchar(100)='this_is_a_long_file_name.*',
@Query varchar(1000);
IF (OBJECT_ID(N'tempdb.dbo.#FirstTable') IS NULL)
BEGIN
CREATE TABLE #FirstTable (Name VARCHAR(256));
END;
SET QUOTED_IDENTIFIER ON;
SET @Query ='master.dbo.xp_cmdshell ''dir "'+ @FilePath + '\' + @SourceFiles +'" /b''';
SELECT LEN(@FilePath + '\' + @SourceFiles);
PRINT @Query;
INSERT #FirstTable EXEC(@Query);
SELECT * FROM #FirstTable;
Запуск без ошибок. Значение @Query
, показанное на вкладке «Сообщения», отображается как:
master.dbo.xp_cmdshell 'dir "C:\Users\Solomon\AppData\Local\Microsoft\HelpViewer2.0\TableOfContentsFilterCache\VisualStudio11\en-US\this_is_a_long_file_name.*" /b'
Теперь, до изменений, которые я предложил, была ошибка. Результат исходного кода (с теми же тестовыми значениями):
Вкладка «Результаты»:
129
Вкладка "Сообщения":
master.dbo.xp_cmdshell "dir C:\Users\Solomon\AppData\Local\Microsoft\HelpViewer2.0\TableOfContentsFilterCache\VisualStudio11\en-US\this_is_a_long_file_name.* /b"
Сообщение 103, уровень 15, состояние 4, строка 1
Идентификатор, начинающийся с "dir C:\Users\Solomon\AppData\Local\Microsoft\HelpViewer2.0\TableOfContentsFilterCache\VisualStudio11\en-US\this_is_a_long_file_n", слишком длинная. Максимальная длина 128.
person
Solomon Rutzky
schedule
23.11.2016