MS Sql Server 2005 のテーブルにいくつかの varbinary データを格納しています。入力としてクエリを受け取り (クエリが varbinary の単一の列が返されることを保証するとしましょう)、バイトをディスクに出力する (1 つのファイル) SQL コードを持っている人はいますか?行ごとに?) これは以前に何千回も尋ねられたと確信していますが、Google はほとんど .net ソリューションを思いつきます。SQL ソリューションが必要です。
8 に答える
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
これを追加して、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");
}
T-SQL ではなく BCP を使用できますが、うまく機能します。
BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:\file.txt" -T
古い投稿であることはわかっていますが、次のことが機能しない理由と修正方法を理解しました。
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 のようなバイナリ エディターを使用してプレフィックス バイトを削除すると、すべてが完全に実行されます。:-)
あなたが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);
}
ただの代替案です。フリーウェアの Toad for SQL サーバーを使用して、エディターから直接保存できます。
彼らの Web サイトhttps://www.toadworld.comにアクセスして、そこでフリーウェアを入手するか、フルバージョンの 30 日間の試用版を入手してください。ダウンロードの下で、Toad for SQL server を選択します。
保存したい画像がある行で、Toad で通常の select ステートメントを実行します。結果が表示されたら、バイト画像列をクリックすると、これが PDF ドキュメントの場合は右側に [PDF] タブが表示され、左側に [画像] タブが表示されます。タブをクリックすると、画像またはファイルを保存するための保存ロゴが下部に表示されます。
SQL はデータベース オブジェクトを操作するように設計されているため、SQL の観点からは他に何も存在しません。確かにxp_cmdshell
、オペレーティング システムと対話できるようにする拡張プロシージャはありますが、これらは独自の拡張機能であり、T-SQL の一部ではありません。
おそらく最も近い方法は、SQL Server 2008 のバイナリ型に FILESTREAM 属性を使用することです。これにより、データベースを使用する代わりに、一部の列をファイルとしてフォルダーに直接保存できます。
FILESTREAM ストレージは、パフォーマンスを向上させるためにデータベースから大きなファイルを保持するように設計されており、ファイルへの直接アクセスを許可するためのものではないことに注意してください (つまり、T-SQL にはまだファイル システムの概念がありません)。私の意見では、SQL からファイルシステムに直接アクセスすると、データベースの目的の一部が無効になります (主に構造化された方法でデータが格納されます)。
したがって、Dustin のアドバイスに従い、BCP やその他のデータ ダンパーなどのツールを使用することをお勧めします。