1

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

我的一个存储过程中有一个神秘的问题,它从数据库中获取一些数据,然后通过 bcp(成功)创建一些文件,然后它尝试执行几个移动命令,即使文件夹它们都失败了肯定存在并且服务以系统管理员身份运行。

这是它试图执行的代码:

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 创建它们之前是否存在延迟,并且当它执行移动时它们还不存在?有任何想法吗?

4

2 回答 2

0

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

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

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

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

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

如果您仍然不想放弃 xp_cmdshell,我的建议是创建您自己的存储过程作为通用包装器。如果您决定更改数据库提供程序,那么迁移的痛苦会小得多。

于 2012-10-26T03:03:20.293 回答
0

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

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

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

在作业的第一次运行中,前一次运行的文件不存在,所以我们得到了错误。

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

于 2012-10-18T18:43:57.640 回答