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