如何在'xp_cmdshell'DIR命令中使用超过128个字符的路径

时间:2016-11-23 06:29:31

标签: sql-server xp-cmdshell

我正在尝试使用超过128个字符的SQL Server路径获取目录中的文件列表。它不起作用。

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。

2 个答案:

答案 0 :(得分:2)

此问题的关键是错误消息的措辞(强调添加):

  

开头的标识符

标识符是SQL Server中对象或项目的名称,不是文字字符串。例如,masterdboxp_cmdshell都是标识符。

所以,你有两个选择:

简单修复(但不是最佳实践)

标识符的问题是指向SET QUOTED_IDENTIFIER ON行的线索。只需将ON更改为OFF即可实现此功能。但是,如果路径和/或文件名模式中有空格(例如 C:\ Program Files(x86)\ ),则会出现错误。

最佳实践修复(这仍然非常简单)

在shell命令周围使用单引号而不是双引号。由于您在Dynamic SQL中创建命令,因此在两个实例中都需要两个单引号。所以,...xp_cmdshell ''dir ... /b''...

如果路径本身有空格,那么路径周围需要双引号:...xp_cmdshell ''dir "..." /b''...

因此,完整的语法是:

SET @Query ='master.dbo.xp_cmdshell ''dir "'+ @FilePath + '\' + @SourceFiles +'" /b''';

将其放入完整的原始代码,以及一个长路径名称以及一个额外的SELECTPRINT,看看发生了什么,你得到:

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”

     

Msg 103,Level 15,State 4,Line 1
  以'dir C:\ Users \ Solomon \ AppData \ Local \ Microsoft \ HelpViewer2.0 \ TableOfContentsFilterCache \ VisualStudio11 \ en-US \ this_is_a_long_file_n'开头的标识符太长。最大长度为128。

答案 1 :(得分:1)

为了好玩,我创建了一个目录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 "'+@file_path+'\'+@src_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;