【问题标题】:How to use path having more than 128 character in 'xp_cmdshell' DIR command如何在“xp_cmdshell”DIR 命令中使用超过 128 个字符的路径
【发布时间】:2016-11-23 06:29:31
【问题描述】:

我正在尝试使用超过 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。

【问题讨论】:

    标签: sql-server xp-cmdshell


    【解决方案1】:

    这个问题的关键是错误信息的措辞(强调):

    开头的标识符

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

    所以,你有两个选择:

    简单修复(但不是最佳做法)

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

    最佳实践修复(这仍然很容易)

    在 shell 命令周围使用单引号而不是双引号。并且由于您是在动态 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"

    消息 103,第 15 级,状态 4,第 1 行
    以 'dir C:\Users\Solomon\AppData\Local\Microsoft\HelpViewer2.0\TableOfContentsFilterCache\VisualStudio11\en-US\this_is_a_long_file_n' 开头的标识符太长。最大长度为 128。

    【讨论】:

    • 如果我们使用单引号,它不会被认为是 xp_cmdshell 中的一个命令,所以它会显示错误为“系统找不到指定的路径。”
    • @Husen xp_cmdshell 存储过程需要一个 VARCHAR 或 NVARCHAR 参数。这就是为什么您需要在完整的DIR 命令周围加上单引号。由于您在 VARCHAR 本身内格式化此命令,因此您需要将它们加倍,即放两个单引号以在最终字符串中获得一个单引号。
    • 我已经尝试了所有的排列和组合。请检查本地环境,然后建议语法。
    • @Husen 我已经提供了该语法,但如果很难将其放回代码中,我已经用完整的脚本更新了我的答案。我还添加了对错误的完整解释和第二个(虽然不是那么好)选项。
    • @srutzky 阅读它...我想知道为什么 OP 认为他需要一个明确的 QUOTED_IDENTIFIER 设置为 ON。我认为他想做的事没有必要。
    【解决方案2】:

    为了好玩,我创建了一个目录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;
    

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 2022-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-25
      • 2013-02-18
      相关资源
      最近更新 更多