Theo Wikipedia, "Chèn hàng loạt là một quy trình hoặc phương pháp được cung cấp bởi hệ thống quản lý cơ sở dữ liệu để tải nhiều hàng dữ liệu vào một bảng cơ sở dữ liệu." Nếu chúng tôi điều chỉnh giải thích này phù hợp với câu lệnh BULK INSERT, chèn hàng loạt cho phép nhập các tệp dữ liệu bên ngoài vào SQL Server. Giả sử rằng tổ chức của chúng tôi có tệp CSV gồm 1.500.000 hàng và chúng tôi muốn nhập tệp này vào một bảng cụ thể trong SQL Server, vì vậy chúng tôi có thể dễ dàng sử dụng câu lệnh BULK INSERT trong SQL Server. Chắc chắn, chúng tôi có thể tìm thấy một số phương pháp nhập để xử lý quy trình nhập tệp CSV này, ví dụ:chúng ta có thể sử dụng bcp ( b ulk c opy p rogram), Thuật sĩ Nhập và Xuất SQL Server hoặc gói Dịch vụ Tích hợp Máy chủ SQL. Tuy nhiên, câu lệnh BULK INSERT nhanh hơn và mạnh mẽ hơn nhiều so với việc sử dụng các phương pháp luận khác. Một ưu điểm khác của câu lệnh chèn hàng loạt là nó cung cấp một số tham số giúp xác định cài đặt của quá trình chèn hàng loạt.
Đầu tiên, chúng tôi sẽ bắt đầu một mẫu rất cơ bản và sau đó chúng tôi sẽ đi qua các tình huống phức tạp khác nhau.
Chuẩn bị
Trước khi bắt đầu các mẫu, chúng tôi cần một tệp CSV mẫu. Do đó, chúng tôi sẽ tải xuống tệp CSV mẫu từ trang web E for Excel, nơi bạn có thể tìm thấy các tệp CSV mẫu khác nhau với số hàng khác nhau. Bạn có thể tìm thấy liên kết ở cuối bài viết. Trong các tình huống của chúng tôi, chúng tôi sẽ sử dụng 1.500.000 Hồ sơ bán hàng. Tải xuống tệp zip, sau đó giải nén tệp CSV và đặt tệp đó vào ổ đĩa cục bộ của bạn.
Nhập tệp CSV vào bảng SQL Server
Tình huống-1:Đích và tệp CSV có số cột bằng nhau
Trong trường hợp đầu tiên này, chúng tôi sẽ nhập tệp CSV vào bảng đích ở dạng đơn giản nhất. Tôi đã đặt tệp CSV mẫu của mình trên ổ C:và bây giờ chúng ta sẽ tạo một bảng để nhập dữ liệu từ tệp CSV.
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 )
Câu lệnh BULK INSERT sau đây nhập tệp CSV vào bảng Bán hàng.
BULK INSERT Sales FROM 'C:\1500000 Sales Records.csv' WITH (FIRSTROW = 2, FIELDTERMINATOR = ',', ROWTERMINATOR='\n' );
Bây giờ, chúng tôi sẽ giải thích các tham số của câu lệnh chèn số lượng lớn ở trên.
Tham số FIRSTROW chỉ định điểm bắt đầu của câu lệnh chèn. Trong ví dụ dưới đây, chúng tôi muốn bỏ qua tiêu đề cột vì vậy chúng tôi đặt tham số này thành 2.
FIELDTERMINATOR xác định ký tự ngăn cách các trường với nhau. SQL Server phát hiện từng trường theo cách như vậy. ROWTERMINATOR không khác nhiều so với FIELDTERMINATOR. Nó xác định ký tự phân tách của các hàng. Trong tệp CSV mẫu, dấu chấm trường rất rõ ràng và nó là dấu phẩy (,). Nhưng làm thế nào chúng ta có thể phát hiện một bộ hủy trường? Mở tệp CSV trong Notepad ++, sau đó điều hướng đến Xem-> Hiển thị Biểu tượng-> Hiển thị Tất cả Biểu đồ, sau đó tìm các ký tự CRLF ở cuối mỗi trường.
CR =Vận chuyển hàng trở lại và LF =Nguồn cấp hàng. Chúng được sử dụng để đánh dấu ngắt dòng trong tệp văn bản và nó được biểu thị bằng ký tự “\ n” trong câu lệnh chèn hàng loạt.
Một phương pháp khác để nhập tệp CSV vào bảng với sự trợ giúp của chèn hàng loạt là sử dụng tham số FORMAT. Xin lưu ý rằng tham số FORMAT chỉ có sẵn trong SQL Server 2017 và các phiên bản mới hơn.
BULK INSERT Sales FROM 'C:\1500000 Sales Records.csv' WITH (FORMAT='CSV' , FIRSTROW = 2);
Bây giờ chúng ta sẽ phân tích một kịch bản khác.
Tình huống-2:Bảng đích có nhiều cột hơn rồi đến tệp CSV
Trong trường hợp này, chúng tôi sẽ thêm khóa chính vào bảng Bán hàng và trường hợp này phá vỡ ánh xạ cột bình đẳng. Bây giờ, chúng tôi sẽ tạo bảng Bán hàng với khóa chính, hãy thử nhập tệp CSV thông qua lệnh chèn hàng loạt và sau đó chúng tôi sẽ gặp lỗi.
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' );
Để khắc phục lỗi này, chúng tôi sẽ tạo chế độ xem bảng Bán hàng với các cột ánh xạ tới tệp CSV và nhập dữ liệu CSV qua chế độ xem này vào bảng Bán hàng.
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' );
Tình huống-3:Làm cách nào để tách và tải tệp CSV thành kích thước hàng loạt nhỏ?
SQL Server có được một khóa tới bảng đích trong quá trình chèn hàng loạt. Theo mặc định, nếu bạn không đặt tham số BATCHSIZE, SQL Server sẽ mở một giao dịch và chèn toàn bộ dữ liệu CSV vào giao dịch này. Tuy nhiên, nếu bạn đặt tham số BATCHSIZE, SQL Server sẽ chia dữ liệu CSV theo giá trị tham số này. Trong mẫu sau, chúng tôi sẽ chia toàn bộ dữ liệu CSV thành nhiều bộ gồm 300.000 hàng, mỗi bộ. Do đó, dữ liệu sẽ được nhập vào 5 lần.
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 );
Nếu câu lệnh chèn hàng loạt của bạn không bao gồm tham số kích thước hàng loạt (BATCHSIZE), một lỗi sẽ xảy ra và SQL Server sẽ khôi phục toàn bộ quá trình chèn hàng loạt. Mặt khác, nếu bạn đặt tham số kích thước lô thành câu lệnh chèn số lượng lớn, SQL Server sẽ chỉ khôi phục phần được chia này nơi xảy ra lỗi. Không có giá trị tối ưu hoặc tốt nhất cho tham số này vì giá trị tham số này có thể được thay đổi theo yêu cầu hệ thống cơ sở dữ liệu của bạn.
Tình huống-4:Cách hủy quy trình nhập khi gặp lỗi?
Trong một số trường hợp sao chép hàng loạt, nếu xảy ra lỗi, chúng tôi có thể muốn hủy quá trình sao chép hàng loạt hoặc tiếp tục quá trình. Tham số MAXERRORS cho phép chúng tôi chỉ định số lỗi tối đa. Nếu quá trình chèn hàng loạt đạt đến giá trị lỗi tối đa này, hoạt động nhập hàng loạt sẽ bị hủy và khôi phục. Giá trị mặc định cho tham số này là 10.
Trong ví dụ sau, chúng tôi sẽ cố ý làm hỏng kiểu dữ liệu trong 3 hàng của tệp CSV và đặt tham số MAXERRORS thành 2. Do đó, toàn bộ hoạt động chèn hàng loạt sẽ bị hủy vì số lỗi vượt quá thông số lỗi tối đa.
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);
Bây giờ chúng ta sẽ thay đổi tham số lỗi tối đa thành 4. Do đó, câu lệnh chèn hàng loạt sẽ bỏ qua các hàng này và chèn các hàng có cấu trúc dữ liệu thích hợp, đồng thời hoàn tất quá trình chèn hàng loạt.
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
Ngoài ra, nếu chúng ta sử dụng đồng thời cả hai tham số kích thước hàng loạt và lỗi tối đa, thì quá trình sao chép hàng loạt sẽ không hủy bỏ toàn bộ hoạt động chèn, nó sẽ chỉ hủy bỏ phần đã chia.
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
Trong phần đầu tiên của loạt bài viết này, chúng tôi đã thảo luận về những điều cơ bản của việc sử dụng thao tác chèn hàng loạt trong SQL Server và phân tích một số tình huống gần với các vấn đề trong đời thực.
Chèn hàng loạt SQL Server - Phần 2
Các liên kết hữu ích:
Chèn hàng loạt
E for Excel - Tệp CSV mẫu / Tập dữ liệu để kiểm tra (cho đến 1,5 triệu bản ghi)
Tải xuống Notepad ++
Công cụ hữu ích:
dbForge Data Pump - một phần bổ trợ SSMS để lấp đầy cơ sở dữ liệu SQL với dữ liệu nguồn bên ngoài và di chuyển dữ liệu giữa các hệ thống.