Script pour sauvegarder les données varbinary sur le disque

j'ai quelques données varbinary stockées dans une table dans MS Sql Server 2005. Est-ce que quelqu'un a du code SQL qui prend une requête comme entrée (disons que la requête garantit qu'une seule colonne de varbinary est retournée) et produit les octets vers le disque (un fichier par ligne?) Je suis sûr que cela a été demandé des milliers de fois auparavant, mais Googling vient avec la plupart du temps des solutions .net. Je veux une solution SQL.

21
demandé sur SFun28 2010-10-30 01:30:03

7 réponses

l'approche PCA ne fonctionne pas pour moi. Les octets qu'il écrit sur le disque ne peuvent pas être desérialisés de nouveau vers les objets .net que j'ai stockés. Cela signifie que les octets sur le disque ne sont pas équivalents à ce qui est stocké. Peut-être que BCP écrit une sorte d'en-tête. Je ne suis pas sûr.

j'ai trouvé le code suivant ici en bas de l'article. Il fonctionne très bien! Bien qu'il soit destiné aux images BMP stockées, il fonctionne avec n'importe quel varbinaire.

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
30
répondu SFun28 2010-11-03 14:22:43

Vous pouvez utiliser BCP, pas T-SQL, mais fonctionne bien.

BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:\file.txt" -T
12
répondu Dustin Laine 2010-10-29 21:39:52

j'ajoute ceci pour construire sur la réponse de JohnOpincar, de sorte que les autres qui veulent utiliser LinqPad puissent obtenir une solution de travail plus rapidement.

/*
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");
}
7
répondu Atron Seige 2016-11-10 05:53:48

je sais que c'est un vieux post, mais j'ai compris pourquoi le suivant ne fonctionne pas et comment résoudre le problème:

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

la raison est la longueur du préfixe de put de bcp au tout début du fichier. Il est soit 4 bytes ou 8 bytes, dépend du type de données de la colonne FileContent (texte, ntext, image: 4 varchar (max), varbinary ( max): 8 Refer to https://msdn.microsoft.com/en-us/library/ms190779.aspx)

Utilisez un éditeur binaire, comme celui de Visual Studio, pour supprimer préfixe octets, et tout fonctionne parfaitement. : -)

4
répondu Sean Zhu 2015-12-22 17:15:01

si vous avez linqpad, cela fonctionne:

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);
}
2
répondu JohnOpincar 2016-01-28 21:37:47

juste une alternative. Vous pouvez utiliser le Toad gratuit pour SQL server et enregistrer directement depuis l'éditeur.

Vous pouvez aller sur leur site https://www.toadworld.com et obtenir le freeware ou un 30 jours d'essai de la version complète. Son sous Télécharger et de choisir Crapaud pour SQL server.

enter image description here

vous faites une instruction select régulière dans Toad sur la ligne qui a l'image que vous voulez enregistrer. Quand vous voyez les résultats vous vous pouvez cliquer sur la colonne byte image et à droite vous voyez un onglet PDF s'il s'agit d'un document PDF ou à gauche vous voyez un onglet Image. Lorsque vous cliquez sur l'onglet, vous pouvez voir l'enregistrer logo en bas pour enregistrer l'image ou le fichier.

2
répondu Vilhelm 2018-09-06 10:18:00

SQL est conçu pour fonctionner avec des objets de base de données, donc de son point de vue, rien d'autre n'existe. Bien sûr, il y a des procédures étendues comme xp_cmdshell qui vous permettent d'interagir avec le système d'exploitation, mais ce sont des extensions propriétaires et ne font pas partie de T-SQL.

peut-être que l'approche la plus proche serait d'utiliser L'attribut FILESTREAM pour les types binaires de SQL Server 2008, qui permettent de stocker certaines colonnes directement sous forme de fichiers dans un dossier au lieu d'utiliser le base de données:

FILESTREAM overview

Remarque: que le stockage FILESTREAM est conçu pour maintenir de grands fichiers hors de la base de données afin d'augmenter les performances, et non pour permettre un accès direct aux fichiers (i.e. T-SQL n'a toujours pas le concept d'un système de fichiers). Je suis d'avis que L'accès direct au système de fichiers à partir de SQL va faire échouer certains des objectifs d'une base de données (principalement avoir des données stockées dans une structure façon.)

je recommande donc de suivre les conseils de Dustin et d'utiliser un outil comme BCP ou tout autre dumper de données.

0
répondu Alberto Martinez 2010-10-31 13:24:42