如何在 'xp_cmdshell' DIR 命令中使用超过 128 个字符的路径
How to use path having more than 128 character in 'xp_cmdshell' DIR command
我正在尝试使用 SQL 超过 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
这会产生以下错误:
The identifier that starts with 'dir D:....' is too long. Maximum length is 128.
这个问题的关键是报错信息的写法(重点加了):
The identifier that starts with
标识符是SQL服务器中的对象或项目的名称,不是文字字符串。例如master
、dbo
、xp_cmdshell
都是标识符。
所以,你有两个选择:
简单修复(但不是最佳实践)
标识符的问题是指向 SET QUOTED_IDENTIFIER ON
行的线索。只需将 ON
更改为 OFF
即可。但是,如果路径 and/or 文件名模式中存在 space(例如 C:\Program Files (x86)\),您将收到错误消息。
最佳实践修复(仍然很简单)
在 shell 命令周围使用单引号而不是双引号。由于您是在 Dynamic SQL 中创建命令,因此在两个实例中它都需要是两个单引号。所以,...xp_cmdshell ''dir ... /b''...
如果路径本身有任何spaces,那么你需要在路径周围加上双引号:...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
的值显示在 "Messages" 选项卡中,呈现为:
master.dbo.xp_cmdshell 'dir "C:\Users\Solomon\AppData\Local\Microsoft\HelpViewer2.0\TableOfContentsFilterCache\VisualStudio11\en-US\this_is_a_long_file_name.*" /b'
现在,在我建议的更改之前,出现了一个错误。原始代码的输出(具有相同的测试值)是:
"Results" 选项卡:
129
"Messages" 选项卡:
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
The identifier that starts with 'dir C:\Users\Solomon\AppData\Local\Microsoft\HelpViewer2.0\TableOfContentsFilterCache\VisualStudio11\en-US\this_is_a_long_file_n' is too long. Maximum length is 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 "'+@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;
我正在尝试使用 SQL 超过 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
这会产生以下错误:
The identifier that starts with 'dir D:....' is too long. Maximum length is 128.
这个问题的关键是报错信息的写法(重点加了):
The identifier that starts with
标识符是SQL服务器中的对象或项目的名称,不是文字字符串。例如master
、dbo
、xp_cmdshell
都是标识符。
所以,你有两个选择:
简单修复(但不是最佳实践)
标识符的问题是指向 SET QUOTED_IDENTIFIER ON
行的线索。只需将 ON
更改为 OFF
即可。但是,如果路径 and/or 文件名模式中存在 space(例如 C:\Program Files (x86)\),您将收到错误消息。
最佳实践修复(仍然很简单)
在 shell 命令周围使用单引号而不是双引号。由于您是在 Dynamic SQL 中创建命令,因此在两个实例中它都需要是两个单引号。所以,...xp_cmdshell ''dir ... /b''...
如果路径本身有任何spaces,那么你需要在路径周围加上双引号:...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
的值显示在 "Messages" 选项卡中,呈现为:
master.dbo.xp_cmdshell 'dir "C:\Users\Solomon\AppData\Local\Microsoft\HelpViewer2.0\TableOfContentsFilterCache\VisualStudio11\en-US\this_is_a_long_file_name.*" /b'
现在,在我建议的更改之前,出现了一个错误。原始代码的输出(具有相同的测试值)是:
"Results" 选项卡:
129
"Messages" 选项卡:
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
The identifier that starts with 'dir C:\Users\Solomon\AppData\Local\Microsoft\HelpViewer2.0\TableOfContentsFilterCache\VisualStudio11\en-US\this_is_a_long_file_n' is too long. Maximum length is 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 "'+@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;