sql >> Databáze >  >> RDS >> Sqlserver

Ukládání binárních datových typů na SQL Server

Úvod

Každodenní práce zřídka vyžaduje ukládání binárních dat přímo do databázových sloupců. V některých případech je však velmi užitečný.

Na rozdíl od všeobecného mínění mohou bajtová pole pomoci s podstatně více než jen s ukládáním velkých binárních objektů (dokumenty, multimédia atd.). Také je lze použít k ukládání hodnot hash a vzorových dat pro rychlejší vyhledávání/analýzu na vysoké úrovni. Nebo mohou obsahovat bajty, které jsou v některých elektronických relé ve stavech ZAPNUTO/VYPNUTO. Jakmile začneme přemýšlet o hardwarových datech uložených v databázích, aplikace se stanou zjevnějšími.

Na rozdíl od datových typů VARCHAR, kde se musíte starat o porovnávání a kódové stránky, jsou binární datové typy série bajtů (někdy nazývané bajtová pole v objektově orientovaných programovacích jazycích), a to buď pevné (BINAR ) nebo proměnné (VARBINAR ) velikosti.

Abychom lépe porozuměli podrobnostem o binárních typech, nejprve provedeme krátký úvod do hexadecimálních čísel, což je způsob, jakým jsou tato data interně uložena.

Šestnáctková čísla

Pokud jste na střední škole přeskočili hodinu o hexadecimálních číslech, dobrý úvod najdete na specializované stránce Wikipedie. Zde se můžete seznámit s tímto formátem číslování.

Pro pochopení tohoto článku je důležité vědět, že SQL Server Management Studio zobrazuje binární data v hexadecimálním formátu s předponou „0x“.

Mezi hexadecimálním a desítkovým formátem číslování není velký rozdíl. Hexadecimální formát používá znaménka se základem 16 (0-9 a A-F) namísto desetinného zápisu se základem 10 (0-9). Hodnoty A-F jsou čísla 10-15 ze zápisu desítkového číslování.

To je důvod, proč používáme hexadecimální zápis. Protože jeden bajt obsahuje 8 bitů, což umožňuje 256 diskrétních celých čísel, je výhodné prezentovat bajty v hexadecimálním formátu. Pokud cílíme na rozsah 0-256, je reprezentován jako 00-FF v hexadecimálním zápisu. Předpona v Management studiu slouží ke srozumitelnosti čtení, ke zdůraznění, že zobrazujeme hexadecimální čísla a nikoli výchozí desetinné hodnoty.

Ruční převod hodnoty pomocí CAST()

Protože binární hodnoty jsou ve svém přísném smyslu řetězce, můžeme je převést z číselného na znakový formát pomocí CAST nebo CONVERT metody SQL.

Podívejte se na příklad, který používá CAST metoda:

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

Použití převodních stylů s CONVERT()

CONVERT() na rozdíl od CAST() , má další možnost použití převodních stylů.

Převodní styly jsou šablony pro pravidla používaná v procesu převodu. CONVERT() se většinou používá v operacích datum/čas. Když jsou data v nestandardním formátu, lze je použít při převodu binárních hodnot. Všimněte si, že binární datové typy nepodporují automatický převod datových typů bez správných hodnot parametrů. Potom SQL Server vyvolá výjimku.

Pokud se podíváme na CONVERT() definice metody, vidíme, že potřebuje dva povinné a jeden volitelný parametr.

První parametr je cílový datový typ a druhý je hodnota, ze které bychom chtěli převádět. Třetí parametr v našem případě může mít hodnotu 1 nebo 2 . Hodnota 1 znamená, že CONVERT() by měl vstupní řetězec považovat za hexadecimální řetězec v textovém formátu a hodnotu 2 znamená, že chcete přeskočit 0x prefix.

Podívejte se na příklady zobrazující toto chování:

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);  

Rozdíl mezi BINARY a VARBINARY

U binárních dat můžeme použít dva druhy datových typů – pevnou velikost a proměnnou velikost. Nebo jsou BINARY a VARBINARY.

Pokud použijeme proměnnou s pevnou velikostí, obsah se vždy rozšíří na definovanou velikost s odsazením 0x00 … – chybí vycpávka v proměnné délce. Při použití operace součtu na těchto proměnných se neprovádí žádné sčítání. Hodnoty jsou připojeny jedna k druhé. Totéž je jako s typy řetězců.

K demonstraci chování prefixů použijeme dva jednoduché příklady s operací binárního součtu:

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)); 

Každá hodnota v příkazu BINARY(2) je doplněna o 0x00 hodnoty.

Použití celočíselných hodnot s binárními datovými typy

SQL Server je dodáván s vestavěnými metodami pro převod mezi číselnými typy a binárními typy. Ukázali jsme to tam, kde jsme otočili Test řetězec do binárního formátu a poté zpět do formátu BIGINT, bez použití funkce ASCII():

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

Jednoduchý převod mezi znakovými a hexadecimálními hodnotami

Pro převod mezi charterovými a hexadecimálními hodnotami je užitečné napsat vlastní funkci, která by tuto operaci prováděla konzistentně. Jeden možný přístup je níže:

-- 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') 

Tentokrát jsme použili hodnotu parametru 2 v CONVERT() funkce. Ukazuje, že tato operace by neměla být mapována na kód ASCII a měla by být zobrazena bez 0x… prefix.

Příkladová případová studie:Ukládání fotografií v binárním typu SQL Server

K tomuto problému obvykle přistupujeme implementací vlastní windows/webové aplikace nebo napsáním vlastního SSIS balíčku s C# kódem. V tomto příkladu použiji pouze jazyk SQL. Může být užitečnější, pokud nemáte přístup k nástrojům front-end databáze.

Pro ukládání obrázků do databázové tabulky musíme vytvořit tabulku, která je bude obsahovat. Tabulka musí obsahovat sloupce obsahující název obrázku a binární obsah obrázku:

-- 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

Abychom umožnili načítání binárních dat do instance SQL Serveru, musíme server nakonfigurovat se dvěma možnostmi:

  • Povolte možnost Postupy automatizace OLE
  • Přidělení oprávnění BulkAdmin uživateli provádějícímu proces importu obrázku.

Níže uvedený skript provede úlohu pod vysoce privilegovaným uživatelem 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 

Nyní můžeme začít psát proceduru importu a exportu:

-- 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

Nyní můžeme tyto procedury používat z libovolné klientské aplikace velmi jednoduchým způsobem.

Představme si, že máme obrázky v C:\Pictures\Inp složka. K načtení těchto obrázků musíme provést následující kód:

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

Podobným způsobem můžeme exportovat data do C:\Pictures\Out složka:

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

Závěr

Volba mezi binárními objekty nebo alternativními způsoby ukládání binárních dat v databázi (například ukládání cest souborů do databáze a jejich načítání z diskového/cloudového úložiště) závisí na více faktorech.

Obecným pravidlem je, že pokud je soubor menší než 256 kB, měli byste jej uložit do sloupců VARBINARY. Pokud jsou binární soubory větší než jeden megabajt, měli byste je uložit do systému souborů. Pokud máte FILESTREAM dostupný v SQL Serveru verze 2008 a vyšší, uchovává soubory pod transakční kontrolou jako logickou součást databáze.

Pokud se rozhodnete uložit binární soubory do tabulky serveru SQL Server, použijte samostatnou tabulku pouze pro binární obsah. Potom můžete optimalizovat umístění úložiště a přistupovat k enginu, pravděpodobně pomocí samostatných souborů a skupin souborů pro tuto tabulku. Podrobné informace jsou k dispozici v oficiálním článku společnosti Microsoft.

V každém případě vyzkoušejte oba přístupy a použijte ten, který nejlépe vyhovuje vašim potřebám.


  1. Co je nového v PostgreSQL 11

  2. Jak spustit SQL Server 2017 a 2019 současně na počítači Mac

  3. Nejlepší způsob, jak zkontrolovat prázdnou nebo nulovou hodnotu

  4. Funkce POWER() v Oracle