Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Przechowywanie binarnych typów danych w SQL Server

Wprowadzenie

Codzienna praca rzadko wymaga przechowywania danych binarnych bezpośrednio w kolumnach bazy danych. Jednak w niektórych przypadkach jest to bardzo przydatne.

Wbrew powszechnej opinii tablice bajtowe mogą pomóc w znacznie więcej niż tylko przechowywaniu dużych obiektów binarnych (dokumentów, multimediów itp.). Mogą być również używane do przechowywania wartości skrótu i ​​przykładowych danych w celu szybszego wyszukiwania/analizy wysokiego poziomu. Lub mogą zawierać bajty, które są w stanie ON/OFF w jakimś przekaźniku elektronicznym. Gdy tylko zaczniemy myśleć o danych sprzętowych przechowywanych w bazach danych, aplikacje stają się bardziej widoczne.

W przeciwieństwie do typów danych VARCHAR, w których musisz zadbać o sortowanie i strony kodowe, binarne typy danych to serie bajtów (czasami nazywane tablicami bajtów w obiektowych językach programowania), albo o stałym (BINAR ) albo zmiennym (VARBINAR ) rozmiarze.

Aby lepiej zrozumieć szczegóły dotyczące typów binarnych, najpierw zrobimy krótkie wprowadzenie do liczb szesnastkowych, czyli sposobu wewnętrznego przechowywania tych danych.

Liczby szesnastkowe

Jeśli pominąłeś zajęcia na liczbach szesnastkowych w szkole średniej, dobre wprowadzenie można znaleźć na dedykowanej stronie Wikipedii. Tam możesz zapoznać się z tym formatem numeracji.

Aby zrozumieć ten artykuł, ważne jest, aby wiedzieć, że SQL Server Management Studio wyświetla dane binarne w formacie szesnastkowym z prefiksem „0x”.

Nie ma dużej różnicy między formatem szesnastkowym a dziesiętnym. Format szesnastkowy wykorzystuje znaki o podstawie 16 (0-9 i A-F) zamiast podstawy 10 w notacji dziesiętnej (0-9). Wartości A-F są liczbami 10-15 z zapisu liczb dziesiętnych.

Dlatego używamy notacji szesnastkowej. Ponieważ jeden bajt zawiera 8 bitów, co pozwala na 256 dyskretnych liczb całkowitych, korzystne jest przedstawienie bajtów w formacie szesnastkowym. Jeśli celujemy w zakres 0-256, jest on reprezentowany jako 00-FF w notacji szesnastkowej. Prefiks w Studio zarządzania służy do przejrzystości czytania, aby podkreślić, że pokazujemy liczby szesnastkowe, a nie domyślne wartości dziesiętne.

Ręczna konwersja wartości za pomocą CAST()

Ponieważ wartości binarne są, w ścisłym tego słowa znaczeniu, ciągami, możemy je przekonwertować z formatu liczbowego na znakowy za pomocą CAST lub KONWERTOWAĆ Metody SQL.

Spójrz na przykład, w którym użyto CAST metoda:

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

Używanie stylów konwersji za pomocą funkcji CONVERT()

KONWERSJA() metoda, w przeciwieństwie do CAST() , ma dodatkową opcję używania stylów konwersji.

Style konwersji to szablony reguł używanych w procesie konwersji. KONWERSJA() jest używany głównie w operacjach daty/czasu. Gdy dane są w niestandardowym formacie, można je wykorzystać do konwersji wartości binarnych. Należy zauważyć, że typy danych binarnych nie obsługują automatycznej konwersji typu danych bez odpowiednich wartości parametrów. Następnie SQL Server zgłosi wyjątek.

Jeśli spojrzymy na CONVERT() definicja metody, widzimy, że wymaga ona dwóch parametrów obowiązkowych i jednego opcjonalnego.

Pierwszy parametr to docelowy typ danych, a drugi to wartość, z której chcemy dokonać konwersji. Trzeci parametr w naszym przypadku może mieć wartość 1 lub 2 . Wartość 1 oznacza, że ​​KONWERSJA() powinien traktować ciąg wejściowy jako ciąg szesnastkowy w formacie tekstowym, a wartość 2 oznacza, że ​​chcesz pominąć 0x prefiks.

Spójrz na przykłady pokazujące to zachowanie:

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

Różnica między BINARY i VARBINARY

W przypadku danych binarnych możemy używać dwóch rodzajów typów danych – stałego rozmiaru i zmiennego rozmiaru. Lub są to BINARY i VARBINARY.

Jeśli używamy zmiennej o stałym rozmiarze, zawartość jest zawsze rozszerzana do określonego rozmiaru z dopełnieniem 0x00 … – nie ma wyściółki o zmiennej długości. Użycie operacji sumowania na tych zmiennych nie powoduje dodawania. Wartości są dołączane do siebie. To samo dotyczy typów stringów.

Aby zademonstrować zachowanie prefiksu, użyjemy dwóch prostych przykładów z operacją sumy binarnej:

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żda wartość w instrukcji BINARY(2) jest poprzedzona przyrostkiem 0x00 wartości.

Używanie wartości całkowitych z binarnymi typami danych

SQL Server zawiera wbudowane metody konwersji między typami liczbowymi i binarnymi. Pokazaliśmy to, gdy włączyliśmy Test do formatu binarnego, a następnie z powrotem do formatu BIGINT, bez użycia funkcji ASCII():

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

Prosta konwersja między wartościami znakowymi i szesnastkowymi

Aby dokonać konwersji między wartościami czarterowymi i szesnastkowymi, warto napisać funkcję niestandardową, która wykona tę operację konsekwentnie. Jedno z możliwych podejść jest poniżej:

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

Tym razem użyliśmy wartości parametru 2 w CONVERT() funkcjonować. Pokazuje, że ta operacja nie powinna być mapowana na kod ASCII i wyświetlana bez 0x… prefiks.

Przykładowe studium przypadku:przechowywanie zdjęć w formacie binarnym SQL Server

Zwykle podchodzimy do tego problemu, implementując niestandardową aplikację Windows/Web lub pisząc niestandardowy pakiet SSIS z kodem C#. W tym przykładzie użyję tylko języka SQL. Może to być bardziej przydatne, jeśli nie masz dostępu do narzędzi frontonu bazy danych.

Aby przechowywać zdjęcia w tabeli bazy danych, musimy stworzyć tabelę, która będzie je przechowywać. Tabela musi zawierać kolumny zawierające nazwę obrazu i zawartość binarną obrazu:

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

Aby umożliwić ładowanie danych binarnych do instancji SQL Server, musimy skonfigurować serwer z dwiema opcjami:

  • Włącz opcję Procedury automatyzacji OLE
  • Przyznawanie uprawnień BulkAdmin użytkownikowi wykonującemu proces importowania obrazu.

Poniższy skrypt wykona zadanie dla uprzywilejowanego użytkownika instancji 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 

Teraz możemy zacząć pisać procedurę importu i eksportu:

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

Teraz możemy w bardzo prosty sposób korzystać z tych procedur z dowolnej aplikacji klienckiej.

Wyobraźmy sobie, że mamy zdjęcia w C:\Pictures\Inp teczka. Aby załadować te obrazki, musimy wykonać następujący kod:

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

W podobny sposób możemy wyeksportować dane do C:\Pictures\Out folder:

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

Wniosek

Wybór między obiektami binarnymi lub alternatywnymi sposobami przechowywania danych binarnych w bazie danych (na przykład przechowywanie ścieżek plików w bazie danych i pobieranie ich z dysku/chmury) zależy od wielu czynników.

Ogólna zasada jest taka, że ​​jeśli plik jest mniejszy niż 256 kilobajtów, należy go przechowywać w kolumnach VARBINARY. Jeśli pliki binarne są większe niż jeden megabajt, należy je przechowywać w systemie plików. Jeśli masz FILESTREAM dostępny w wersji SQL Server 2008 i nowszych, utrzymuje on pliki pod kontrolą transakcyjną jako logiczną część bazy danych.

Jeśli zdecydujesz się przechowywać pliki binarne w tabeli programu SQL Server, użyj oddzielnej tabeli tylko dla zawartości binarnej. Następnie możesz zoptymalizować jego lokalizację przechowywania i uzyskać dostęp do silnika, prawdopodobnie używając oddzielnych plików i grup plików dla tej tabeli. Szczegółowe informacje są dostępne w oficjalnym artykule Microsoft.

W każdym razie przetestuj oba podejścia i użyj tego, które najlepiej odpowiada Twoim potrzebom.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Usuń wypełnienie podczas wysyłania wyników zapytania w wiadomości e-mail z serwera SQL (T-SQL)

  2. Zmień nazwę kolumny w SQL Server (T-SQL)

  3. Instalowanie sterowników Microsoft SQL Server JDBC w narzędziach Pentaho Data Integration i BA Server

  4. Instalowanie wystąpienia klastra pracy awaryjnej programu SQL Server — część 1

  5. Jak pobrać nazwy pól z tabeli tymczasowej (SQL Server 2008)