xp_cmdshell错误“文件名,目录名称或卷标语法不正确。”

时间:2012-10-18 06:02:41

标签: sql-server xp-cmdshell

我正在将一些代码部署到生产环境中,这是从SQL 2000到SQL 2008的系统升级。

我的一个存储过程中有一个神秘的问题,它从数据库中获取一些数据,然后通过bcp(successfull)创建一些文件,然后它尝试执行一些移动命令,它们都失败了虽然文件夹肯定存在,服务正在以sysadmin身份运行。

这是它试图执行的代码:

set @cmd_string = 'move '+ @OutPath_AllCards + '*.* '+ @ArchivePath_AllCards
delete from @tbl_xp_cmdshell_output
Insert @tbl_xp_cmdshell_output exec @error_temp = master.dbo.xp_cmdshell @cmd_string

这是我回来的错误消息

xp_cmdshell Error Executing "move H:\Transfer\CHAD\Outbound\AllCards\*.* H:\Transfer\CHAD\Outbound\AllCards\Archive\" 

返回的命令行错误是

"The filename, directory name, or volume label syntax is incorrect."

这在数据库的相同设置UAT版本中工作正常

有什么建议吗?

更新

如果源目录中没有文件,我可以重现错误。我认为源目录中可能应该有文件,但是我想知道在bcp创建之前是否存在滞后,当它执行移动时它们还不存在?有什么想法吗?

2 个答案:

答案 0 :(得分:0)

好的,这里有一点愚蠢的程序员(我和其他人)综合症。

发生错误是因为当你执行语句时移动c:\ Source *。* c:\ dest并且源中没有文件然后我遇到的错误将返回(“文件名,目录名或卷标语法是不正确的。“)。

代码假定前一次运行的文件存在,因此在bcping新文件之前将它们移开。 bcp并不像我之前想的那样首先发生。

在第一次运行时,上一次运行的文件不存在,所以我们收到了错误。

所以,我想解决方案是复制然后在文件夹中删除,而不是试图将其作为移动。

答案 1 :(得分:0)

请注意,如果从数据库服务器(在您的情况下为SQL Server)中调用外部OS命令,则本地计算机就是该数据库服务器,而不一定是您的本地计算机。

正如您在具体示例中提到的H:驱动器,我假设这是一个网络映射驱动器(可能是带有用户主文件夹的驱动器)。但是,您可能遇到这种映射存在于UAT数据库服务器上但不存在于PROD数据库服务器上的情况。当DEV或UAT服务器位于某人的本地计算机上时,并且当软件移动到下一个部署阶段时,情况开始出现奇怪的错误。

在你的情况下,使用UNC路径(带有前导双反斜杠)而不是类似DOS的路径会更安全。这将使您在任何地方都可以独立进行驱动器映射。

但是,我个人不喜欢将OS调用嵌入到数据库引擎中 - 它会产生混乱。我更喜欢使用shell脚本(UNIX)或命令脚本(Windows),我调用存储过程(通过isql或osql或sqlplus),然后运行其他可执行文件。使用BCP我没有看到从存储过程运行它的任何好处 - 您仍然无法使用本地临时表,因为BCP打开自己的连接。

另外,我经常看到人们不关心操作是否成功的源代码。使用BCP需要付出相当大的努力来验证它是否成功(它总是返回0 - 成功,以及与isql,osql,sqlplus等相同的故事)。您必须检查错误文件并确保它为空以确定它是正常的。所有这些都不适合存储过程。当然,你可以启动另一个可执行文件进行检查,但在我看来,这不是正确的方法。数据库服务器应该用于数据库操作,而不是用于完全运行应用程序。

如果您仍然不想放弃xp_cmdshell,我的建议是创建您自己的存储过程作为通用包装器。如果您决定更改数据库提供程序,则可以轻松迁移。

相关问题