2016-02-26 39 views

回答

0

我通過結合來自不同地方的許多小技巧找到了答案,並希望在這裏整理它們,因爲似乎沒有人看到完整的過程。

我有兩個表,分別叫PhotosPhotoBinaryPhotos包含至少一個PhotoID BIGINTBase64數據VARCHAR(MAX),以及根據需要增加FolderName - NVARCHAR(15)。我還有一個BIT字段將它們標記爲isProcessedPhotoBinary有一個VARBINARY(MAX)列,應該是空的。

第二個表有兩個目的,它以二進制格式保存轉換後的base64編碼圖像,並且允許我解決BCP在使用「格式文件時從表中導出數據時不會讓您跳過列的事實「來指定列格式。所以在我的情況下,數據必須獨自坐在一張桌子上,我確實試着從一個視圖中看到它,但是前面提到的問題是不允許跳過id列。

主存儲過程有一個bcp命令,該命令取決於使用以下SQL創建的.fmt文件。我非常肯定,我必須使用純文本編輯器編輯生成的文件,將8更改爲0,表示SQLBINARY之後的前綴長度。我不能在主存儲過程的命令中使用-n開關,因爲它導致在結果文件中放入一個8字節前綴,這使得它成爲無效的jpeg。所以,我用編輯過的格式文件來解決這個問題。

DECLARE @command VARCHAR(4000); 
SET @command = 'bcp DB.dbo.PhotoBinary format nul -T -n -f "A:\pathto\photobinary.fmt"'; 
EXEC xp_cmdshell @command; 

然後我在我運行到圖像導出到相應的文件夾的存儲過程如下:

DECLARE @command  VARCHAR(4000), 
     @photoId  BIGINT, 
     @imageFileName VARCHAR(128), 
     @folderName NVARCHAR(15), 
     @basePath  NVARCHAR(500), 
     @fullPath  NVARCHAR(500), 
     @dbServerName NVARCHAR(100); 

DECLARE @directories TABLE (directory nvarchar(255), depth INT); 

-- The location of the output folder 
SET @basePath = '\\server\share'; 
-- The server that the photobinary db is on 
SET @dbServerName = 'localhost'; 

-- @basePath values, get the folders already in the output folder 
INSERT INTO @directories(directory, depth) EXEC master.sys.xp_dirtree @basePath; 

-- Cursor for each image in table that hasn't already been exported 
DECLARE photo_cursor CURSOR FOR 
    SELECT PhotoID, 
      'some_image_' + CAST(PhotoID AS NVARCHAR) + '.jpg', 
      FolderName 
    FROM dbo.Photos 
    WHERE isProcessed = 0; 

OPEN photo_cursor 

FETCH NEXT FROM photo_cursor 
    INTO @photoId, 
     @imageFileName, 
     @folderName; 

WHILE (@@FETCH_STATUS = 0) -- Cursor loop 
BEGIN 
    -- Create the @basePath directory 
    IF NOT EXISTS (SELECT * FROM @directories WHERE directory = @folderName) 
    BEGIN 
     SET @fullPath = @basePath + '\' + @folderName; 
     EXEC master.dbo.xp_create_subdir @fullPath; 
    END 


    -- move and convert the base64 encoded image to a separate table in binary format 
    -- it should be the only row in the table 
    INSERT INTO DB.dbo.PhotoBinary (PhotoBinary) 
     SELECT CAST(N'' AS xml).value('xs:base64Binary(sql:column("Base64"))', 'varbinary(max)') 
      FROM DB.dbo.Photos 
      WHERE PhotoID = @photoId; 

    -- This command uses the command-line BCP tool to "bulk export" the image data in binary to an "archive" file that just happens to be a jpg 
    SET @command = 'bcp "SELECT TOP 1 PhotoBinary FROM DB.dbo.PhotoBinary" queryout "' + @basePath + '\' + @folderName + '\' + @imageFileName + '" -T -S ' + @dbServerName + ' -f "A:\pathto\photobinary.fmt"'; 
    EXEC xp_cmdshell @command; 

    -- clean up the photo data 
    DELETE FROM DB.dbo.PhotoBinary; 

    -- mark photo as processed 
    UPDATE DB.dbo.Photos SET isProcessed = 1 WHERE PhotoID = @photoId; 

    FETCH NEXT FROM photo_cursor 
     INTO @photoId, 
      @imageFileName, 
      @folderName; 
    END -- cursor loop 

CLOSE photo_cursor 

DEALLOCATE photo_cursor 
+0

你問的問題19分鐘前,那麼你19分鐘前回答了 – Mark

+2

@Mark然後你評論1分鐘前... – Klors

相關問題