这个问题的关键是错误信息的措辞(强调):
以
开头的标识符
标识符是 SQL Server 中对象或项的名称,不是文字字符串。例如,master、dbo 和 xp_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''';
将它放入完整的原始代码中,加上一个长路径名和一个额外的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。