Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Stockage des types de données binaires dans SQL Server

Présentation

Le travail quotidien nécessite rarement de stocker des données binaires directement dans les colonnes de la base de données. Cependant, il est très utile dans certains cas.

Contrairement à l'opinion populaire, les tableaux d'octets peuvent aider à bien plus que simplement stocker de gros objets binaires (documents, multimédia, etc.). En outre, ils peuvent être utilisés pour stocker des valeurs de hachage et des exemples de données pour une recherche/analyse de haut niveau plus rapide. Ou, ils peuvent contenir des octets qui sont dans des états ON/OFF dans certains relais électroniques. Dès que nous commençons à penser aux données matérielles stockées dans les bases de données, les applications deviennent plus apparentes.

Contrairement aux types de données VARCHAR où vous devez vous occuper du classement et des pages de code, les types de données binaires sont des séries d'octets (parfois appelés tableaux d'octets dans les langages de programmation orientés objet), de taille fixe (BINAR) ou variable (VARBINAR).

Pour mieux comprendre les détails sur les types binaires, nous allons d'abord faire une brève introduction aux nombres hexadécimaux, qui sont la façon dont ces données sont stockées en interne.

Nombres hexadécimaux

Si vous avez sauté le cours sur les nombres hexadécimaux au lycée, une bonne introduction se trouve sur une page Wikipédia dédiée. Là, vous pourrez vous familiariser avec ce format de numérotation.

Pour comprendre cet article, il est important de savoir que SQL Server Management Studio affiche les données binaires au format hexadécimal avec le préfixe "0x".

Il n'y a pas de grande différence entre le format de numérotation hexadécimal et décimal. Le format hexadécimal utilise des signes en base 16 (0-9 et A-F) au lieu de la base 10 de la notation décimale (0-9). Les valeurs A-F sont les nombres 10-15 de la notation de numérotation décimale.

C'est pourquoi nous utilisons la notation hexadécimale. Puisqu'un octet contient 8 bits, permettant 256 nombres entiers discrets, il est avantageux de présenter les octets au format hexadécimal. Si nous ciblons la plage 0-256, elle est représentée par 00-FF en notation hexadécimale. Le préfixe dans Management studio est destiné à la clarté de la lecture, pour souligner que nous affichons des nombres hexadécimaux et non la valeur par défaut valeurs décimales.

Conversion de valeur manuelle à l'aide de CAST()

Étant donné que les valeurs binaires sont, au sens strict, des chaînes, nous pouvons les convertir du format nombre au format caractère en utilisant CAST ou CONVERTIR Méthodes SQL.

Jetez un oeil à l'exemple qui utilise le CAST méthode :

SELECT CAST('HexTest' AS VARBINARY);                 
SELECT CAST(0x48657854657374 AS VARCHAR);  

Utilisation des styles de conversion avec CONVERT()

CONVERT() méthode, contrairement à CAST() , a une option supplémentaire pour utiliser les styles de conversion.

Les styles de conversion sont des modèles de règles utilisées dans le processus de conversion. CONVERT() est principalement utilisé dans les opérations de date/heure. Lorsque les données sont dans un format non standard, elles peuvent être utilisées dans la conversion de valeurs binaires. Notez que les types de données binaires ne prennent pas en charge la conversion automatique des types de données sans les valeurs de paramètre appropriées en place. Ensuite, SQL Server lèvera une exception.

Si nous regardons le CONVERT() définition de la méthode, nous voyons qu'elle prend deux paramètres obligatoires et un paramètre facultatif.

Le premier paramètre est le type de données cible et le second est la valeur à partir de laquelle nous souhaitons effectuer la conversion. Le troisième paramètre, dans notre cas, peut valoir 1 ou 2 . Valeur 1 signifie que CONVERT() doit considérer la chaîne d'entrée comme une chaîne hexadécimale au format texte et la valeur 2 signifie que vous voulez ignorer le 0x préfixe.

Jetez un œil aux exemples illustrant ce comportement :

DECLARE @MyString NVARCHAR(500)='0x48657854657374';

SELECT CONVERT(VARBINARY(MAX), @MyString );    
-- String value is directly converted to binary value - we wanted is to change the datatype 
-- and not convert "0x.." prefix to the hexadecimal value

SELECT CONVERT(VARBINARY(MAX), @MyString, 1);  

Différence entre BINARY et VARBINARY

Avec les données binaires, nous pouvons utiliser deux types de types de données :taille fixe et taille variable. Ou, ils sont BINARY et VARBINARY.

Si nous utilisons la variable de taille fixe, le contenu est toujours étendu à sa taille définie avec un rembourrage de 0x00 … – il n'y a pas de rembourrage de longueur variable. L'utilisation de l'opération de somme sur ces variables n'entraîne aucune addition exécutée. Les valeurs sont ajoutées les unes aux autres. Il en va de même pour les types de chaîne.

Pour illustrer le comportement du préfixe, nous utiliserons deux exemples simples avec l'opération de somme binaire :

SELECT CAST('T' AS BINARY(1)) + CAST('e' AS BINARY(1)) + CAST('s' AS BINARY(1)) + CAST('t' AS BINARY(1)); 
SELECT CAST('T' AS BINARY(2)) + CAST('e' AS BINARY(2)) + CAST('s' AS BINARY(2)) + CAST('t' AS BINARY(2)); 

Chaque valeur dans l'instruction BINARY(2) est postfixée avec 0x00 valeurs.

Utilisation de valeurs entières avec des types de données binaires

SQL Server est livré avec des méthodes intégrées pour convertir entre les types numériques et les types binaires. Nous l'avons démontré lorsque nous avons réalisé le test string au format binaire, puis de nouveau au format BIGINT, sans utiliser la fonction ASCII() :

SELECT CAST('Test' AS VARBINARY(MAX));
SELECT CAST(CAST('Test' AS VARBINARY(MAX)) AS BIGINT);

Conversion simple entre caractères et valeurs hexadécimales

Pour convertir entre les valeurs charte et hexadécimales, il est utile d'écrire une fonction personnalisée qui effectuerait cette opération de manière cohérente. Une approche possible est ci-dessous :

-- DROP FUNCTION dbo.FN_CH_HEX(@InputValue CHAR(1)

CREATE OR ALTER FUNCTION dbo.FN_CH_HEX(@InputValue CHAR(1))
RETURNS CHAR(2)
AS
BEGIN
    RETURN(CONVERT(CHAR(2), CAST(@InputValue AS BINARY(1)), 2));
END;

-- SELECT dbo.FN_CH_HEX('A') 

Cette fois, nous avons utilisé la valeur de paramètre 2 dans le CONVERT() une fonction. Cela montre que cette opération ne doit pas être mappée au code ASCII et être affichée sans le 0x… préfixe.

Exemple d'étude de cas :stockage de photos au format binaire SQL Server

Nous abordons généralement ce problème en implémentant une application Windows/Web personnalisée ou en écrivant un package SSIS personnalisé avec du code C#. Dans cet exemple, j'utiliserai uniquement le langage SQL. Cela peut être plus utile si vous n'avez pas accès aux outils frontaux de la base de données.

Pour stocker des images dans la table de la base de données, nous devons créer une table qui les contiendra. Le tableau doit inclure des colonnes contenant le nom de l'image et le contenu binaire de l'image :

-- DROP TABLE T_BINARY_DATA 

CREATE TABLE T_BINARY_DATA 
(
   PICTURE_ID INT IDENTITY(1,1) PRIMARY KEY,
   PICTURE_NAME NVARCHAR(100),
   PICTURE_FILE_NAME NVARCHAR(500),
   PICTURE_DATA VARBINARY(MAX)
)
GO

Pour activer le chargement des données binaires sur l'instance SQL Server, nous devons configurer le serveur avec deux options :

  • Activer l'option Procédures d'automatisation OLE
  • Attribuer le privilège BulkAdmin à l'utilisateur exécutant le processus d'importation d'images.

Le script ci-dessous effectuera la tâche sous l'utilisateur à privilèges élevés de l'instance SQL Server :

USE MASTER
GO
EXEC sp_configure 'show advanced options', 1; 
GO
RECONFIGURE; 
GO
EXEC sp_configure 'Ole Automation Procedures', 1; 
GO
RECONFIGURE; 
GO
-- Add 'bulkadmin' to the correct user
ALTER SERVER ROLE [bulkadmin] ADD MEMBER [NT AUTHORITY\SYSTEM] 
GO 

Nous pouvons maintenant commencer à écrire la procédure d'importation et d'exportation :

-- DROP PROCEDURE dbo.proc_ImportBinary 
-- DROP PROCEDURE dbo.proc_ExportBinary 

CREATE PROCEDURE dbo.proc_ImportBinary 
(
     @PICTURE_NAME      NVARCHAR(100)
   , @FOLDER_PATH       NVARCHAR(500)
   , @PICTURE_FILE_NAME NVARCHAR(500)
   )
AS
BEGIN
   DECLARE @OutputPath NVARCHAR(4000);
   DECLARE @TSQLDYN    NVARCHAR(4000);
   
   SET @OutputPath = CONCAT(@OutputPath,'\',@PICTURE_FILE_NAME)
   SET @TSQLDYN = 'INSERT INTO T_BINARY_DATA(PICTURE_NAME,PICTURE_FILE_NAME,PICTURE_DATA) '
                + 'SELECT ' + '''' + @PICTURE_NAME + '''' + ',' + '''' + @PICTURE_FILE_NAME + '''' + ', * ' 
				+ '  FROM Openrowset( Bulk ' + '''' + @OutputPath + '''' + ', Single_Blob) as img'

   EXEC (@TSQLDYN)   
END
GO


CREATE PROCEDURE dbo.proc_ExportBinary (
     @PICTURE_NAME      NVARCHAR(100)
   , @FOLDER_PATH       NVARCHAR(500)
   , @PICTURE_FILE_NAME NVARCHAR(500)
   )
AS
BEGIN
   DECLARE @Binary     VARBINARY (max);
   DECLARE @OutputPath NVARCHAR(4000);
   DECLARE @Obj        INT
 
   SELECT @Binary = (
         SELECT CONVERT(VARBINARY(max), PICTURE_DATA , 1)
           FROM T_BINARY_DATA 
          WHERE PICTURE_NAME  = @PICTURE_NAME
         );
 
   SET @OutputPath = CONCAT(@FOLDER_PATH, '\', @PICTURE_FILE_NAME);
         
    BEGIN TRY
     EXEC sp_OACreate 'ADODB.Stream', @Obj OUTPUT;
     EXEC sp_OASetProperty @Obj ,'Type',1;
     EXEC sp_OAMethod @Obj,'Open';
     EXEC sp_OAMethod @Obj,'Write', NULL, @Binary;
     EXEC sp_OAMethod @Obj,'SaveToFile', NULL, @OutputPath, 2;
     EXEC sp_OAMethod @Obj,'Close';
     EXEC sp_OADestroy @Obj;
    END TRY
    
 BEGIN CATCH
  EXEC sp_OADestroy @Obj;
 END CATCH
 
   SET NOCOUNT OFF
END
GO

Nous pouvons maintenant utiliser ces procédures à partir de n'importe quelle application cliente de manière très simple.

Imaginons que nous ayons des images dans le C:\Pictures\Inp dossier. Pour charger ces images, nous devons exécuter le code suivant :

-- Load picture to table row
exec dbo.proc_ImportBinary ‘MyPic’, ‘C:\Pictures\Inp’, ‘MyPic.jpg’ 

De la même manière, nous pouvons exporter des données vers C:\Pictures\Out dossier :

exec dbo.proc_ExportBinary ‘MyPic’, ‘C:\Pictures\Out’, ‘MyPic.jpg’

Conclusion

Le choix entre des objets binaires ou des moyens alternatifs de stockage de données binaires dans une base de données (par exemple, stocker des chemins de fichiers dans une base de données et les récupérer à partir du stockage sur disque/cloud) dépend de plusieurs facteurs.

La règle générale est que si la taille du fichier est inférieure à 256 kilo-octets, vous devez le stocker dans les colonnes VARBINARY. Si les fichiers binaires sont supérieurs à un mégaoctet, vous devez les stocker sur le système de fichiers. Si vous avez FILESTREAM disponible dans les versions 2008 et supérieures de SQL Server, il conserve les fichiers sous contrôle transactionnel en tant que partie logique de la base de données.

Si vous décidez de stocker des fichiers binaires dans la table SQL Server, utilisez une table distincte uniquement pour le contenu binaire. Ensuite, vous pouvez optimiser son emplacement de stockage et accéder au moteur, probablement en utilisant des fichiers et des groupes de fichiers distincts pour cette table. Les informations détaillées sont disponibles dans l'article officiel de Microsoft.

Dans tous les cas, testez les deux approches et utilisez celle qui correspond le mieux à vos besoins.