44

MS Sql Server 2005 のテーブルにいくつかの varbinary データを格納しています。入力としてクエリを受け取り (クエリが varbinary の単一の列が返されることを保証するとしましょう)、バイトをディスクに出力する (1 つのファイル) SQL コードを持っている人はいますか?行ごとに?) これは以前に何千回も尋ねられたと確信していますが、Google はほとんど .net ソリューションを思いつきます。SQL ソリューションが必要です。

4

8 に答える 8

48

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

記事の下部に次のコードが見つかりましたそれはうまくいきます!保存された 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
于 2010-11-03T14:22:43.743 に答える
26

これを追加して、JohnOpincar's answerに基づいて構築します。これにより、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");
}
于 2016-11-10T05:53:48.737 に答える
13

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

BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:\file.txt" -T
于 2010-10-29T21:39:52.117 に答える
7

古い投稿であることはわかっていますが、次のことが機能しない理由と修正方法を理解しました。

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

その理由は、bcp がプレフィックス長をファイルの最初に置くためです。4 バイトまたは 8 バイトのいずれかで、FileContent 列のデータ型によって異なります (text、ntext、image: 4 varchar(max)、varbinary(max): 8 https://msdn.microsoft.com/en-usを参照してください)。 /library/ms190779.aspx )

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

于 2015-12-21T22:56:22.860 に答える
6

あなたが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);
}
于 2016-01-28T21:37:47.143 に答える
1

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

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

ここに画像の説明を入力

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

于 2016-10-13T10:51:29.917 に答える
-1

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

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

ファイルストリームの概要

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

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

于 2010-10-31T13:24:42.500 に答える