Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过存储过程从SQL导出二进制文件数据(图像)_Sql_Sql Server_Sql Server 2008_Tsql - Fatal编程技术网

通过存储过程从SQL导出二进制文件数据(图像)

通过存储过程从SQL导出二进制文件数据(图像),sql,sql-server,sql-server-2008,tsql,Sql,Sql Server,Sql Server 2008,Tsql,我正在尝试导出大量图像文件,这些文件作为二进制数据存储在SQL数据库中 对于用SQL编写存储过程来说,我还是一个新手,因此我遇到了一些非常有用的指南,介绍了如何归档存储过程,但我似乎遗漏了一些东西 我正在本地运行SQL Server 2008 R2,并试图将文件写入C:\驱动器上的文件夹 以下是我到目前为止的业务部分: BEGIN DECLARE @cmd VARCHAR(8000) DECLARE @result int DECLARE curExportBinaryDocs CURSOR

我正在尝试导出大量图像文件,这些文件作为二进制数据存储在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调用有问题,但我不确定下一步要尝试什么

欢迎提供任何帮助或建议。

首先。。(对此很抱歉;)不要使用光标。。 很抱歉我的帽子

关于游标最糟糕的事情之一是它们可以锁定您的表。我总是为了这些目的(而且速度更快),使用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
declare@totrow int
,@currow int
,@result int
,@nsql nvarchar(最大值)
声明@sqlStatements表(
Id int标识(1,1)
,SqlStatement varchar(最大值)
)
插入
转换为@sqlStatements
选择“查询部分”
从桌子上
设置@totrow=@@rowcount
设置@currow=1

虽然@totrow>0和@currow这里是我的最终工作程序和格式文件。我无法找到更详细的 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    

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

您如何运行SQL?SQL是在用户的凭据下运行的…该用户是否有权在输出文件夹中创建文件?我正在使用常用的windows用户名和windows身份验证登录SQL server。我已设法使用此处概述的方法获得解决方案:但如果可能我想弄清我原来的方法中存在的问题的根源,只是为了安心!我相信你所做的有点错误。你知道SQL Server的“支持文件流的数据库”吗“。它允许您在硬盘上存储Blob,而Blob仍由SQL Server维护。将此blob排序到驱动器后,应用程序只需查询数据库并获取对象。另外,使用游标也不是一件好事(它太慢了)。谢谢Mark,我在得到了一个不同的解决方案后继续使用它,但看到您的评论后,我又去看了一眼。在修改我的代码以避免使用光标,然后与BCP权限和引号的奇怪之处搏斗之后,我现在让它正常工作了!非常感谢。我会对你的回答投赞成票,但我还没有足够高的代表:)@MarkKremers如果你是对的,那么游标是坏的,你会发现while循环是通过游标实现的,游标提供了对性能的更多控制,因此尽管循环比适当的游标表现得更好:嗨,@ChrisMurray,因为本专栏的内容是二进制/原始数据,您可以通过向BCP命令行提供
-N
标志来避免格式化文件,即:
BCP“从[photo]中选择数据,其中ID=123;“queryyout”123.jpg“-S localhost\SQLEXPRESS2008-T-N
我无法生成可以使用-N而不是格式化文件打开的TIF。显然是因为它附加了某种类型的头字节。如果在第一次BCP调用中关闭所有格式选项,它将提示您输入格式参数。除了我设置为零的头字节之外,我接受了默认值。然后,它提示我保存文件,然后使用-f标志在其他BCP请求中引用该文件。
9.0  
1  
1       SQLBINARY       0       0       "\t"     1      Photograph_Data                                  ""