web-dev-qa-db-ja.com

varbinaryデータをディスクに保存するスクリプト

MS Sql Server 2005のテーブルに格納されたvarbinaryデータがあります。クエリを入力として(クエリがvarbinaryの単一の列が返されることをクエリに保証する)SQLバイトを持っていますか?行ごと?)これは以前に何千回も質問されていたと思いますが、グーグルはほとんど.netソリューションを思いつきます。 SQLソリューションが必要です。

31
SFun28

BCPアプローチは私にはうまくいきません。ディスクに書き込むバイトは、保存した.netオブジェクトにデシリアライズすることはできません。これは、ディスク上のバイトが保存されているものと同じではないことを意味します。おそらく、BCPは何らかの種類のヘッダーを書いているのでしょう。よく分かりません。

次のコードを見つけました here 記事の最後に。うまくいきます!保存されたBMP画像を対象としていますが、任意のvarbinaryで動作します。

DECLARE @SQLIMG VARCHAR(MAX),
    @IMG_PATH VARBINARY(MAX),
    @TIMESTAMP VARCHAR(MAX),
    @ObjectToken INT

DECLARE IMGPATH CURSOR FAST_FORWARD FOR 
        SELECT csl_CompanyLogo from mlm_CSCompanySettingsLocalizations

OPEN IMGPATH 

FETCH NEXT FROM IMGPATH INTO @IMG_PATH 

WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @TIMESTAMP = 'd:\' + replace(replace(replace(replace(convert(varchar,getdate(),121),'-',''),':',''),'.',''),' ','') + '.bmp'

        PRINT @TIMESTAMP
        PRINT @SQLIMG

        EXEC sp_OACreate 'ADODB.Stream', @ObjectToken OUTPUT
        EXEC sp_OASetProperty @ObjectToken, 'Type', 1
        EXEC sp_OAMethod @ObjectToken, 'Open'
        EXEC sp_OAMethod @ObjectToken, 'Write', NULL, @IMG_PATH
        EXEC sp_OAMethod @ObjectToken, 'SaveToFile', NULL, @TIMESTAMP, 2
        EXEC sp_OAMethod @ObjectToken, 'Close'
        EXEC sp_OADestroy @ObjectToken

        FETCH NEXT FROM IMGPATH INTO @IMG_PATH 
    END 

CLOSE IMGPATH
DEALLOCATE IMGPATH
35
SFun28

T-SQLではなくBCPを使用できますが、うまく機能します。

BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:\file.txt" -T
13
Dustin Laine

これを追加して、JohnOpincarの答えに基づいて、LinqPadを使用したい他の人が実用的なソリューションをより速く入手できるようにします。

/*
This LinqPad script saves data stored in a VARBINARY field to the specified folder.
1. Connect to SQL server and select the correct database in the connection dropdown (top right)
2. Change the Language to C# Program
3. Change "Attachments" to the name of your table that holds the VARBINARY data
4. Change "AttachmentBuffer" to the name of the field that holds the data
5. Change "Id" to the unique identifier field name
6. Change "1090" to the identity of the record you want to save
7. Change the path to where you want to save the file. Make sure you choose the right extension.

Notes: Windows 10 may give you "Access Denied" error when trying to save directly to C:\. Rather save to a subfolder.
*/

void Main()
{
    var context = this;
    var query = 
        from ci in context.Attachments
        where ci.Id == 1090
        select ci.AttachmentBuffer
    ;
    byte[] result = query.Single().ToArray();
    File.WriteAllBytes(@"c:\DEV\dumpfile.xlsx", result);
    Console.WriteLine("Done");
}
13
Atron Seige

私はそれが古い投稿であることを知っていますが、以下がうまくいかない理由とそれを修正する方法を見つけました:

BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:\file.JPG" -T -N

その理由は、ファイルの先頭にbcp put Prefix Lengthがあるためです。 4バイトまたは8バイトで、FileContent列のデータ型に依存します(text、ntext、image:4 varchar(max)、varbinary(max):8参照 https://msdn.Microsoft.com /en-us/library/ms190779.aspx

Visual Studioのようなバイナリエディターを使用してプレフィックスバイトを削除すると、すべてが完全に実行されます。 :-)

6
Sean Zhu

Linqpadを使用している場合、これは機能します。

void Main()
{
    var context = this;
    var query = 
        from ci in context.Images
        where ci.ImageId == 10
        select ci.Image
    ;
    var result = query.Single ();
    var bytes = Convert.FromBase64String(result);
    File.WriteAllBytes(@"c:\image.bmp", bytes);
}
4
JohnOpincar

ただの代替。 SQL Server用のフリーウェアToadを使用して、エディターから直接保存できます。

彼らのウェブサイト https://www.toadworld.com にアクセスして、そこでフリーウェアを入手するか、フルバージョンの30日間の試用版を入手できます。 [ダウンロード]の下で、Toad for SQL Serverを選択します。

enter image description here

Toadで、保存する画像がある行で通常のselectステートメントを実行します。結果が表示されたら、バイト画像の列をクリックして、右側にPDFタブが表示されます(これがPDFドキュメントまたは左側にある場合[画像]タブが表示されます。タブをクリックすると、画像またはファイルを保存するための保存ロゴが下部に表示されます。

2
Vilhelm

SQLはデータベースオブジェクトを操作するように設計されているため、その観点からは他に存在するものはありません。もちろん、xp_cmdshellのような拡張プロシージャがあり、オペレーティングシステムとやり取りできますが、これらは独自の拡張機能であり、T-SQLの一部ではありません。

おそらく最も近いアプローチは、SQL Server 2008のバイナリタイプにFILESTREAM属性を使用することです。これにより、データベースを使用する代わりに、いくつかの列をファイルとしてフォルダーに直接保存できます。

FILESTREAMの概要

FILESTREAMストレージは、パフォーマンスを向上させるために、データベースから大きなファイルを維持するように設計されていることに注意してください、およびファイルへの直接アクセスを許可するためではありません(つまり、T-SQLにはまだファイルシステムの概念がありません)。私の意見では、SQLからファイルシステムへの直接アクセスは、データベースの目的(主に構造化された方法でデータを保存する)のいくつかの目的を無効にします。

だから、Dustinのアドバイスに従って、BCPや他のデータダンパーなどのツールを使用することをお勧めします。

0