2012-08-30 56 views
7

我試圖導出相當大數量的圖像文件,作爲二進制數據存儲在SQL數據庫內部。通過存儲過程從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 

「@result」總是被設置爲「1」 xp_cmdshell的調用之後(失敗)。所有表名/字段都是正確的,所以我懷疑我的BCP呼叫有問題,但我不確定接下來要嘗試什麼。

任何幫助或建議將是非常受歡迎的。

+0

你是如何運行SQL的? SQL在用戶憑證下運行...該用戶是否有權在輸出文件夾中創建文件? –

+0

我使用通常的Windows用戶名和Windows身份驗證登錄到SQL服務器。 我設法使用這裏概述的方法得到一個解決方案:http://stackoverflow.com/questions/1366544/how-to-export-image-field-to-file但如果可能我想到我的原始方法存在的問題的底部,只是爲了安心! – ChrisMurray

+0

我相信你在做什麼是有點不對。你知道SQL Server的「文件流啓用數據庫」。它允許您將BLOB存儲在硬盤上,而BLOB仍由SQL Server維護。在將BLOBs追加到驅動器之後,您的應用程序只需要對數據庫進行查詢並獲取對象。另外,使用光標不是一件好事(它很慢)。 – gotqn

回答

5

嗯,首先..(以及我們對此深感抱歉;))DON「T使用遊標.. 和遺憾的帽子...

一個有關遊標的最不好的大部分東西都是他們可以鎖定你的表。我一直爲這些目的做(和這是相當快),我用一個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執行它。它是否會給出任何錯誤?

+0

感謝馬克 我得到了一個不同的解決方案工作後,從這個移動,但看到你的意見,我去了又看了一下。 修改我的代碼以避免使用遊標,然後用BCP permisions和引號奇怪來摔跤後,我現在可以正常工作了! 非常感謝。我會投你的迴應,但我沒有足夠的代表:) – ChrisMurray

+0

很高興聽到它幫助:) –

+0

@MarkKremers而你是正確的遊標是壞的,你會發現while循環通過遊標實現,而遊標提供對性能的更多控制,所以while循環比正確的遊標執行得更好:http://sqlblog.com/blogs/aaron_bertrand/archive/2012/01/26/the-fallacy-that-a-while-loop-isn-ta- cursor.aspx – ConstantineK

6

這是我最後的工作程序和格式文件。我無法在一個地方找到 BCP命令,permision設置和格式文件佈局的更詳細的細節,所以這可能對某人有用。

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         "" 

我希望幫助別人。

+1

嗨,@ChrisMurray,由於該列的內容是二進制/原始數據,因此可以通過向BCP命令行提供'-N'標誌來避免格式​​化文件,即:'BCP'SELECT Data FROM [照片] WHERE ID = 123;「查詢「123.jpg」-S localhost \ SQLEXPRESS2008 -T -N' –

+0

我無法生成使用-N而不是格式文件打開的TIF。顯然是因爲它附加了某種頭字節。如果您在第一次BCP呼叫中不使用所有格式化選項,則會提示您輸入格式參數。我接受了除設置爲零的標題字節之外的默認設置。然後它促使我保存我在其他BCP請求中使用-f標誌引用的文件。 – user2027080

相關問題