9

我正在尝试导出大量图像文件,这些文件作为二进制数据在内部存储在 SQL 数据库中。

作为在 SQL 中编写存储过程的新手,我遇到了一些关于如何归档的非常有用的指南,但我似乎遗漏了一些东西。

我在本地运行 SQL Server 2008 R2,并尝试将文件写入 C:\ 驱动器上的文件夹。

这是我到目前为止所拥有的业务部分:

BEGIN
DECLARE @cmd VARCHAR(8000)
DECLARE @result int

DECLARE curExportBinaryDocs CURSOR FAST_FORWARD FOR
SELECT 'BCP "SELECT Photograph_Data FROM [ALBSCH Trial].[dbo].[Photograph] WHERE Photograph_ID = '
  + CAST(Photograph_ID AS VARCHAR(500)) + '" queryout "' + @OutputFilePath 
  + CAST(Photograph_ID AS VARCHAR(500)) + '.jpg"' + ' -n -T'
FROM dbo.Photograph

OPEN curExportBinaryDocs   
FETCH NEXT FROM curExportBinaryDocs INTO @cmd
WHILE @@FETCH_STATUS = 0
  BEGIN
     --PRINT @cmd
     EXEC @result = xp_cmdshell @cmd         
     FETCH NEXT FROM curExportBinaryDocs INTO @cmd
  END 
CLOSE curExportBinaryDocs
DEALLOCATE curExportBinaryDocs
END

在 xp_cmdshell 调用之后,'@result' 始终设置为 '1'(失败)。所有表名/字段都是正确的,所以我怀疑我的 BCP 调用有问题,但我不确定接下来要尝试什么。

非常欢迎任何帮助或建议。

4

2 回答 2

7

好吧,首先..(对此感到抱歉;))不要使用光标..对大写感到抱歉...

游标最糟糕的事情之一是它们可以锁定您的表。我总是为这些目的做什么(而且速度更快),我使用一个 for 循环.. 像这样

declare @totrow int
      , @currow int
      , @result int
      , @nsql nvarchar(max)

declare @sqlStatements table (
  Id int identity(1, 1)
, SqlStatement varchar(max)
)
insert 
into    @sqlStatements
select  'QUERY PART'
from    table

set @totrow = @@rowcount
set @currow = 1
while @totrow > 0 and @currow <= @totrow
begin
  select @nsql = SqlStatement
  from   @SqlStatements
  where  Id = @currow

  exec @result = xp_cmdshell @nsql

  set @currow = @currow + 1
end

对于下一部分,SQL Server 进程是否有足够的权限写入 c: 驱动器?另外,在执行代码时查看消息窗格,也许你可以在那里找到一些东西?

您还可以做什么,尝试手动执行它。只需获取一条 BCP 语句并使用 xp_cmdshell 执行它。它是否给出任何错误?

于 2012-10-02T13:18:49.580 回答
7

这是我的最终工作程序和格式文件。我无法在一个地方找到 BCP 命令、权限设置和格式文件布局的更详细信息,所以也许这对某人有用。

CREATE PROCEDURE [dbo].[ImgExport] 
   @OutputFilePath VARCHAR(500) = 'C:\SQLTest\ '
AS
BEGIN
   DECLARE @totrow int
   DECLARE @currow int
   DECLARE @result int
   DECLARE @nsql nvarchar(4000)
   DECLARE @sqlStatements table (ID int IDENTITY(1, 1),  SqlStatement varchar(max))   

   INSERT
   INTO @sqlStatements
   SELECT 'BCP "SELECT Photograph_Data FROM [ALBSCH_Trial].[dbo].[Photograph] WHERE  Photograph_ID = '''
     + CAST(Photograph_ID AS VARCHAR(500)) + '''" queryout ' + @OutputFilePath 
     + CAST(Photograph_ID AS VARCHAR(500)) + '.jpg -S localhost\SQLEXPRESS2008 -T -f C:\SQLTest\Images.fmt'
   FROM dbo.Photograph  

   SET @totrow = @@ROWCOUNT
   SET @currow = 1
   WHILE @totrow > 0 and @currow <= @totrow
   BEGIN
      SELECT @nsql = SqlStatement
      FROM @sqlStatements
      WHERE ID = @currow
      EXEC @result = xp_cmdshell @nsql
      SET @currow = @currow + 1
   END
END    

格式文件:

9.0  
1  
1       SQLBINARY       0       0       "\t"     1      Photograph_Data                                  ""

我希望这对某人有所帮助。

于 2012-10-04T08:22:19.560 回答