T-SQL Ninja #45

BULK INSERT

Was ist BULK INSERT?

Wenn ihr größere Datenmengen in eine Datenbank bekommen wollt, lautet die Wunderwaffe im SQL Server-Umfeld natürlich SQL Server Integration Services. Wenn ihr das für eine SQL Datenbank in der Cloud machen möchtet, habt ihr erstmal keine SSIS Engine verfügbar, dafür müsst ihr eine Azure Data Factory mit einer Integration Services Runtime verwenden. Doch wenn es nur darum geht, eine formatierte Datei in eine Tabelle zu laden, könnt ihr unter Umständen einen etwas „einfacheren“ Weg gehen und die Daten über ein BULK INSERT-Statement in die Tabelle laden.

Wie könnt ihr BULK INSERT verwenden?

Das BULK INSERT Kommando schreibt die Daten aus einer Datei in eine Tabelle, dabei arbeitet das Kommando automatisch in Batches, deren Größe sich konfigurieren lässt. Um Daten zu haben, die wir importieren können, exportieren wir uns die Daten einer Abfrage auf der WideWorldImporters-Datenbank in eine CSV-Datei. Dafür führen wir im Azure Data Studio folgende Abfrage aus:

SELECT 
     StockItemID
    ,StockItemName
    ,ColorName
    ,RecommendedRetailPrice
    ,TaxRate
    ,UnitPrice
    ,SupplierName
    ,SupplierCategoryName
FROM [Warehouse].[StockItems] si 
LEFT JOIN 
[Warehouse].[Colors] c
ON si.ColorID = c.ColorID
LEFT JOIN [Purchasing].[Suppliers] sup 
ON si.SupplierID = sup.SupplierID
LEFT JOIN [Purchasing].[SupplierCategories] supc
ON sup.SupplierCategoryID = supc.SupplierCategoryID

Diese Daten exportieren wir nun als CSV. Das können wir sowohl im SQL Server Management Studio als auch im Azure Data Studio tun, indem wir die ganze Tabelle markieren und dann kopieren und in Excel einfügen, dort speichert ihr das Resultat dann als CSV. Einfacher wäre es zwar, im Azure Data Studio mit einem Rechtsklick auf die Tabelle und „Save as CSV“ zu speichern, doch dann haben wir keine Kontrolle über Tausendertrennzeichen und Spaltentrenner, die wir aber gegebenenfalls anpassen müssen, denn auch im Jahr 2020 sind die Computer noch nicht so weit, dass Daten, die ihr aus einer Datenbank exportiert habt auch direkt wieder dort einfügen könnt.

Diese CSV-Datei möchten wir nun verwenden, um sie per BULK INSERT in eine neue Tabelle zu laden. Dafür müssen wir zunächst eine Tabelle anlegen. Vor einigen Wochen hattet ihr bereits das Pattern „SELECT TOP 0 INTO“ kennengelernt, wir nun anwenden, um eine Tabelle zu erzeugen:

SELECT TOP 0 
     StockItemID
    ,StockItemName
    ,ColorName
    ,RecommendedRetailPrice
    ,TaxRate
    ,UnitPrice
    ,SupplierName
    ,SupplierCategoryName
INTO Sales.SpecialItems
FROM [Warehouse].[StockItems] si 
LEFT JOIN 
[Warehouse].[Colors] c
ON si.ColorID = c.ColorID
LEFT JOIN [Purchasing].[Suppliers] sup 
ON si.SupplierID = sup.SupplierID
LEFT JOIN [Purchasing].[SupplierCategories] supc
ON sup.SupplierCategoryID = supc.SupplierCategoryID

Jetzt könnt ihr mit BULK INSERT in diese leere Tabelle schreiben, ihr müsst dabei aber darauf achten, dass die Datei auf eurem Datenbankserver existiert, nicht auf eurem Client. Das bedeutet, ihr müsst sie entweder dorthin kopieren oder sie auf einem Netzwerk-Share ablegen oder falls ihr wie wir mit einem Docker Container arbeitet, in den Container kopieren:

docker cp WWI_Items.csv container_name:/tmp/

Wenn ihr die Datei nun sauber bereitgestellt habt (Komma als Trennzeichen für die Spalten, keine Tausendertrennzeichen und Punkt als Dezimaltrennzeichen), sowie alle NULL-Werte gelöscht habt (die Zeichenfolge „NULL“ ist beim Import eben kein NULL-Wert), dann könnt ihr die Datei nun in eure Tabelle laden:

BULK INSERT Sales.SpecialItems
FROM '/tmp/WWI_Items.csv'
WITH ( FORMAT='CSV');

Im WITH-Block habt ihr noch weitere Möglichkeiten, steuernd einzugreifen, ihr könnt beispielsweise den Spaltentrenner setzen.

Vorausgesetzt, eure CSV-Dateien sind sauber und entsprechen dem gewünschten Eingabeformat, habt ihr nun eine technisch einfache Möglichkeit, Daten aus einer CSV-Datei schnell in eine Tabelle eurer Datenbank zu laden.

Referenzen

Ninja-Notebooks @ GitHub

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.