sql >> Database teknologi >  >> RDS >> Sqlserver

SQL Server Bulk Insert – Del 1

Ifølge Wikipedia er "En masseindsættelse en proces eller metode leveret af et databasestyringssystem til at indlæse flere rækker af data i en databasetabel." Hvis vi justerer denne forklaring i overensstemmelse med BULK INSERT-sætningen, tillader bulk-insert import af eksterne datafiler til SQL Server. Antag, at vores organisation har en CSV-fil på 1.500.000 rækker, og vi ønsker at importere denne fil til en bestemt tabel i SQL Server, så vi nemt kan bruge BULK INSERT-sætningen i SQL Server. Vi kan bestemt finde flere importmetoder til at håndtere denne CSV-filimportproces, f.eks. vi kan bruge bcp (b ulk c opy p rogram), SQL Server Import og Export Wizard eller SQL Server Integration Service-pakke. Imidlertid er BULK INSERT-sætningen meget hurtigere og robust end at bruge andre metoder. En anden fordel ved masseindsættelseserklæringen er, at den tilbyder flere parametre, som hjælper med at bestemme indstillinger for masseindsættelsesprocessen.

Først vil vi starte en meget grundlæggende prøve, og derefter vil vi gennemgå forskellige sofistikerede scenarier.

Forberedelse

Før du starter prøverne, har vi brug for en eksempel-CSV-fil. Derfor vil vi downloade en eksempel-CSV-fil fra E for Excel-webstedet, hvor du kan finde forskellige samplede CSV-filer med et andet rækkenummer. Du kan finde linket i slutningen af ​​artiklen. I vores scenarier vil vi bruge 1.500.000 salgsposter. Download en zip-fil, udpak derefter CSV-filen, og placer den på dit lokale drev.

Importer CSV-fil til SQL Server-tabel

Scenario-1:Destination og CSV-fil har lige mange kolonner

I dette første scenarie vil vi importere CSV-filen til destinationstabellen i den enkleste form. Jeg placerede min eksempel-CSV-fil på C:-drevet, og nu vil vi oprette en tabel, som vi vil importere data fra CSV-filen.

DROP TABLE IF EXISTS Sales 

CREATE TABLE [dbo].[Sales](
	[Region] [varchar](50) ,
	[Country] [varchar](50) ,
	[ItemType] [varchar](50) NULL,
	[SalesChannel] [varchar](50) NULL,
	[OrderPriority] [varchar](50) NULL,
	[OrderDate]  datetime,
	[OrderID] bigint NULL,
	[ShipDate] datetime,
	[UnitsSold]  float,
	[UnitPrice] float,
	[UnitCost] float,
	[TotalRevenue] float,
	[TotalCost]  float,
	[TotalProfit] float
)

Følgende BULK INSERT-sætning importerer CSV-filen til salgstabellen.

BULK INSERT Sales
FROM 'C:\1500000 Sales Records.csv'
WITH (FIRSTROW = 2,
    FIELDTERMINATOR = ',',
	ROWTERMINATOR='\n' );

Nu vil vi forklare parametrene for ovenstående bulk insert-sætning.

FIRSTROW-parameteren angiver startpunktet for insert-sætningen. I eksemplet nedenfor ønsker vi at springe kolonneoverskrifter over, så vi indstiller denne parameter til 2.

FIELDTERMINATOR definerer det tegn, som adskiller felter fra hinanden. SQL Server registrerer hvert felt på en sådan måde. ROWTERMINATOR adskiller sig ikke meget fra FIELDTERMINATOR. Det definerer rækkernes adskillelseskarakter. I eksempel-CSV-filen er fieldterminator meget tydelig, og den er et komma (,). Men hvordan kan vi opdage en feltterminator? Åbn CSV-filen i Notesblok++ og naviger derefter til Vis->Vis symbol->Vis alle chartre, og find derefter CRLF-tegnene i slutningen af ​​hvert felt.

CR =Carriage Return og LF =Line Feed. De bruges til at markere et linjeskift i en tekstfil, og det er angivet med tegnet "\n" i bulk insert-sætningen.

En anden metode til at importere en CSV-fil til en tabel ved hjælp af bulk-indsættelse er at bruge parameteren FORMAT. Bemærk venligst, at FORMAT-parameteren kun er tilgængelig i SQL Server 2017 og nyere versioner.

BULK INSERT Sales
FROM 'C:\1500000 Sales Records.csv'
WITH (FORMAT='CSV' , FIRSTROW = 2);

Nu vil vi analysere et andet scenarie.

Scenario-2:Destinationstabel har flere kolonner end CSV-fil

I dette scenarie tilføjer vi en primær nøgle til salgstabellen, og denne sag bryder lighedskolonnetilknytningerne. Nu vil vi oprette salgstabellen med en primær nøgle, prøve at importere CSV-filen gennem bulk insert-kommandoen, og så får vi en fejl.

DROP TABLE IF EXISTS Sales 

CREATE TABLE [dbo].[Sales](
    Id INT PRIMARY KEY IDENTITY (1,1),
	[Region] [varchar](50) ,
	[Country] [varchar](50) ,
	[ItemType] [varchar](50) NULL,
	[SalesChannel] [varchar](50) NULL,
	[OrderPriority] [varchar](50) NULL,
	[OrderDate]  datetime,
	[OrderID] bigint NULL,
	[ShipDate] datetime,
	[UnitsSold]  float,
	[UnitPrice] float,
	[UnitCost] float,
	[TotalRevenue] float,
	[TotalCost]  float,
	[TotalProfit] float
) 

BULK INSERT Sales
FROM 'C:\1500000 Sales Records.csv'
WITH (FIRSTROW = 2,
    FIELDTERMINATOR = ',',
	ROWTERMINATOR='\n' );

For at overvinde denne fejl vil vi oprette en visning af salgstabellen med tilknytning af kolonner til CSV-filen og importere CSV-dataene over denne visning til salgstabellen.

DROP VIEW IF EXISTS VSales 
GO
CREATE VIEW VSales
AS
SELECT Region ,
Country ,
ItemType ,
SalesChannel , 
OrderPriority ,
OrderDate , 
OrderID ,
ShipDate ,
UnitsSold , 
UnitPrice ,
UnitCost ,
TotalRevenue,
TotalCost, 
TotalProfit from Sales

GO 

BULK INSERT VSales
FROM 'C:\1500000 Sales Records.csv'
WITH ( FIRSTROW = 2,
       FIELDTERMINATOR = ',',
	ROWTERMINATOR='\n' );

Scenario-3:Hvordan adskilles og indlæses CSV-filen i en lille batchstørrelse?

SQL Server anskaffer en lås til destinationstabel under bulkinsert-operationen. Som standard, hvis du ikke indstiller parameteren BATCHSIZE, åbner SQL Server en transaktion og indsætter hele CSV-data i denne transaktion. Men hvis du indstiller parameteren BATCHSIZE, deler SQL Server CSV-dataene i henhold til denne parameterværdi. I det følgende eksempel vil vi opdele hele CSV-dataene i flere sæt med hver 300.000 rækker. Således vil dataene blive importeret 5 gange.

DROP TABLE IF EXISTS Sales 

CREATE TABLE [dbo].[Sales](
	[Region] [varchar](50) ,
	[Country] [varchar](50) ,
	[ItemType] [varchar](50) NULL,
	[SalesChannel] [varchar](50) NULL,
	[OrderPriority] [varchar](50) NULL,
	[OrderDate]  datetime,
	[OrderID] bigint NULL,
	[ShipDate] datetime,
	[UnitsSold]  float,
	[UnitPrice] float,
	[UnitCost] float,
	[TotalRevenue] float,
	[TotalCost]  float,
	[TotalProfit] float
) 


BULK INSERT Sales
FROM 'C:\1500000 Sales Records.csv'
WITH (FIRSTROW = 2,
    FIELDTERMINATOR = ',',
	ROWTERMINATOR='\n' ,
	batchsize=300000 );

Hvis din bulk insert-sætning ikke inkluderer batch size (BATCHSIZE) parameteren, vil der opstå en fejl, og SQL Server vil rulle hele bulk insert processen tilbage. På den anden side, hvis du indstiller batchstørrelsesparameteren til bulk insert-sætning, vil SQL Server kun rulle denne delte del tilbage, hvor fejlen opstod. Der er ingen optimal eller bedste værdi for denne parameter, fordi denne parameterværdi kan ændres i henhold til dine databasesystemkrav.

Scenario 4:Sådan annullerer du importproces, når du får en fejl?

I nogle scenarier for massekopiering vil vi måske, hvis der opstår en fejl, enten annullere massekopieringsprocessen eller holde processen i gang. Parameteren MAXERRORS giver os mulighed for at angive det maksimale antal fejl. Hvis masseindsættelsesprocessen når denne maksimale fejlværdi, vil masseimporten blive annulleret og rullet tilbage. Standardværdien for denne parameter er 10.

I det følgende eksempel vil vi med vilje ødelægge datatypen i 3 rækker af CSV-filen og indstille parameteren MAXERRORS til 2. Som følge heraf vil hele masseindsættelsesoperationen blive annulleret, fordi fejlnummeret overstiger parameteren max. fejl.

DROP TABLE IF EXISTS Sales 
CREATE TABLE [dbo].[Sales](
	[Region] [varchar](50) ,
	[Country] [varchar](50) ,
	[ItemType] [varchar](50) NULL,
	[SalesChannel] [varchar](50) NULL,
	[OrderPriority] [varchar](50) NULL,
	[Order Date]  datetime,
	[OrderID] bigint NULL,
	[ShipDate] datetime,
	[UnitsSold]  float,
	[UnitPrice] float,
	[UnitCost] float,
	[TotalRevenue] float,
	[TotalCost]  float,
	[TotalProfit] float
) 

BULK INSERT Sales
FROM 'C:\1500000 Sales Records.csv'
WITH (FIRSTROW = 2,
    FIELDTERMINATOR = ',',
	ROWTERMINATOR='\n' ,
	 MAXERRORS=2);

Nu vil vi ændre max error parameteren til 4. Som et resultat vil bulk insert-sætningen springe disse rækker over og indsætte korrekte datastrukturerede rækker og fuldføre masseindsættelsesprocessen.

DROP TABLE IF EXISTS Sales 
CREATE TABLE [dbo].[Sales](
	[Region] [varchar](50) ,
	[Country] [varchar](50) ,
	[ItemType] [varchar](50) NULL,
	[SalesChannel] [varchar](50) NULL,
	[OrderPriority] [varchar](50) NULL,
	[Order Date]  datetime,
	[OrderID] bigint NULL,
	[ShipDate] datetime,
	[UnitsSold]  float,
	[UnitPrice] float,
	[UnitCost] float,
	[TotalRevenue] float,
	[TotalCost]  float,
	[TotalProfit] float
) 
BULK INSERT Sales
FROM 'C:\1500000 Sales Records.csv'
WITH (FIRSTROW = 2,
    FIELDTERMINATOR = ',',
	ROWTERMINATOR='\n' ,
	 MAXERRORS=4);
	 
	 
	 
SELECT COUNT(*) AS [NumberofImportedRow] FROM Sales

Derudover, hvis vi bruger både batchstørrelse og maksimale fejlparametre på samme tid, vil massekopieringsprocessen ikke annullere hele indsættelsesoperationen, den vil kun annullere den opdelte del.

DROP TABLE IF EXISTS Sales 

CREATE TABLE [dbo].[Sales](
	[Region] [varchar](50) ,
	[Country] [varchar](50) ,
	[ItemType] [varchar](50) NULL,
	[SalesChannel] [varchar](50) NULL,
	[OrderPriority] [varchar](50) NULL,
	[Order Date]  datetime,
	[OrderID] bigint NULL,
	[ShipDate] datetime,
	[UnitsSold]  float,
	[UnitPrice] float,
	[UnitCost] float,
	[TotalRevenue] float,
	[TotalCost]  float,
	[TotalProfit] float
) 
BULK INSERT Sales
FROM 'C:\1500000 Sales Records.csv'
WITH (FIRSTROW = 2,
    FIELDTERMINATOR = ',',
	ROWTERMINATOR='\n' ,
	 MAXERRORS=2,
BATCHSIZE=750000);
GO 
SELECT COUNT(*) AS [NumberofImportedRow] FROM Sales

I denne første del af denne artikelserie diskuterede vi det grundlæggende ved brug af bulkinsert-operationen i SQL Server og analyserede adskillige scenarier, som er tæt på de virkelige problemer.

SQL Server Bulk Insert – Del 2

Nyttige links:

Masseindsats

E for Excel – Eksempel på CSV-filer/datasæt til test (indtil 1,5 millioner registreringer)

Notepad++ download

Nyttigt værktøj:

dbForge Data Pump – et SSMS-tilføjelsesprogram til at fylde SQL-databaser med eksterne kildedata og migrere data mellem systemer.


  1. Returner en liste over e-mails sendt fra SQL Server Database Mail (T-SQL)

  2. Webinar:Nye funktioner i Postgres 12 [Opfølgning]

  3. Fatal fejl:Kald til udefineret funktion sqlsrv_connect()

  4. 8 måder at tilføje en time til et datotidspunkt i MariaDB