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.
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
Vous pouvez utiliser BCP, pas T-SQL, mais fonctionne bien.
BCP "SELECT FileContent FROM table WHERE ID = 1" queryout "C:\file.txt" -T
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");
}
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. : -)
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);
}
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.
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.
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:
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.