Как использовать путь, имеющий более 128 символов в команде «xp_cmdshell» DIR

Я пытаюсь получить список файлов в каталоге с использованием пути SQL Server, имеющего более 128 символов. Он не работает.

DECLARE @FilePath varchar(256)='D:\...',--Path with a length more than 128 char @SourceFiles varchar(100)='Test123456789*.txt', @Query varchar(1000) If Object_Id('tempdb.dbo.#FirstTable') Is NULL CREATE TABLE #FirstTable (Name varchar(256)) SET QUOTED_IDENTIFIER ON SET @Query ='master.dbo.xp_cmdshell "dir '+ @FilePath + '\' + @SourceFiles +' /b"' INSERT #FirstTable exec (@Query) select * from #FirstTable truncate table #FirstTable 

Это дает следующую ошибку:

Идентификатор, начинающийся с 'dir D: ….', слишком длинный. Максимальная длина – 128.

Ключом к этой проблеме является формулировка сообщения об ошибке (выделено курсивом):

Идентификатор , начинающийся с

Идентификатор – это имя объекта или элемента в SQL Server, а не буквальная строка. Например, master , dbo и xp_cmdshell – все идентификаторы.

Итак, у вас есть два варианта:

Простое исправление (но не лучшая практика)

Проблема с идентификаторами – это ключ, указывающий на строку SET QUOTED_IDENTIFIER ON . Простое изменение ON на OFF позволит это работать. Однако вы получите сообщение об ошибке, если в вашем пути и / или шаблоне имени файла есть пробел (например, C: \ Program Files (x86) \ ).

Исправление оптимальной практики (это все еще довольно легко)

Используйте одиночные кавычки вместо двойных кавычек вокруг команды оболочки. И так как вы создаете команду в Dynamic 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 ": C: \ Users \ Solomon \ AppData \ Local \ Microsoft \ HelpViewer2.0 \ TableOfContentsFilterCache \ VisualStudio11 \ en-US \ this_is_a_long_file_name. * / b"

Msg 103, уровень 15, состояние 4, строка 1
Идентификатор, начинающийся с 'dir C: \ Users \ Solomon \ AppData \ Local \ Microsoft \ HelpViewer2.0 \ TableOfContentsFilterCache \ VisualStudio11 \ en-US \ this_is_a_long_file_n' слишком длинный. Максимальная длина – 128.

Просто для удовольствия я создал папку C:\Temp\Temporary folder with an unecessarily long name just to be an example etc etc\Temporary folder with an unecessarily long name just to be an example etc etc (163 символа) и помещена в нем есть test*.txt файлы.

Следующий сценарий не содержит проблем, которые вы описываете.

 DECLARE @file_path NVARCHAR(256)='C:\Temp\Temporary folder with an unecessarily long name just to be an example etc etc\Temporary folder with an unecessarily long name just to be an example etc etc'; PRINT LEN(@file_path); -- prints 163 DECLARE @src_files NVARCHAR(100)='test*.txt'; DECLARE @dir_cmd NVARCHAR(4000)='DIR "'[email protected]_path+'\'[email protected]_files+'" /b'; CREATE TABLE #dir_table(name NVARCHAR(256)); INSERT INTO #dir_table(name) EXEC xp_cmdshell @dir_cmd; SELECT*FROM #dir_table; -- result is a bunch of test*.txt files DROP TABLE #dir_table; 
  • Я чего-то не хватает
  • Что еще я могу использовать, чем xp_cmdshell
  • Ошибка SQL Server xp_cmdshell 5
  • Включить xp_cmdshell не работает
  • Доступ запрещен для включенного xp_cmdshell для пользователя admin
  • Переименовать список файлов с SQL Server 2012
  • Получить результаты от XP_CMDSHELL
  • Как исправить проблему с удаленным / откатом
  • Запустить консольное приложение из SQL Server после асинхронного запуска обновления таблицы?
  • exec xp_cmdshell bcp синтаксис
  • Выполнение пакета SSIS, который ссылается на mso.dll с DTEXEC
  • Interesting Posts

    SQL Server: как упорядочить по дате, если дата <GetDate ()

    Как RETURN @Identity данных instert в spl в asp.net

    Фильтрация записей в SQL Server с использованием даты

    SQL, включая все строки из одной таблицы, независимо от того, сколько из них представлено в другой таблице

    Как обновить строку в другой таблице sql с помощью триггеров

    Обходной путь для WITH RESULT SET для SQL Server 2012

    Вы можете вызвать службу WCF из запроса SQL Server 2008?

    Внедрение эффективных внешних ключей в реляционной базе данных

    Невозможно перетащить хранимую процедуру в dbml designer

    NHibernate не соблюдает точность и масштаб для создания числового столбца (для десятичной)

    Как передать имя столбца в качестве параметра в выражении select SQL Server

    SQL Запланированный запрос заданий, длительность последних прогонов?

    При удалении / повторном импортировании файла .bacpac из v12 Azure SQL Database в те же серверные таблицы не импортируются

    Поиск нечеткой логики для полных имен

    Почему я получаю сообщение об ошибке при использовании ROW_NUMBER в SQL Server?

    Давайте будем гением компьютера.