2008-09-03 33 views
14

Nếu tôi chạy truy vấn sau trong SQL Server 2000 Query Analyzer:Giao dịch Chèn số lượng lớn của Máy chủ SQL?

BULK INSERT OurTable 
FROM 'c:\OurTable.txt' 
WITH (CODEPAGE = 'RAW', DATAFILETYPE = 'char', FIELDTERMINATOR = '\t', ROWS_PER_BATCH = 10000, TABLOCK) 

Mở một file văn bản phù hợp với sơ đồ OurTable cho 40 dòng, nhưng sau đó thay đổi định dạng cho 20 dòng cuối cùng (cho phép nói cuối cùng 20 dòng có ít trường hơn), tôi nhận được lỗi. Tuy nhiên, 40 dòng đầu tiên được cam kết với bảng. Có điều gì đó về cách tôi đang gọi số lượng lớn Chèn mà làm cho nó không được giao dịch, hoặc tôi cần phải làm một cái gì đó rõ ràng để buộc nó để rollback về thất bại?

Trả lời

18

BULK INSERT hoạt động như một loạt câu lệnh riêng lẻ INSERT và do đó, nếu công việc không thành công, nó sẽ không hoàn trả tất cả các lần chèn đã cam kết.

Nó có thể, tuy nhiên, được đặt trong một giao dịch, do đó bạn có thể làm một cái gì đó như thế này:

BEGIN TRANSACTION 
BEGIN TRY 
BULK INSERT OurTable 
FROM 'c:\OurTable.txt' 
WITH (CODEPAGE = 'RAW', DATAFILETYPE = 'char', FIELDTERMINATOR = '\t', 
    ROWS_PER_BATCH = 10000, TABLOCK) 
COMMIT TRANSACTION 
END TRY 
BEGIN CATCH 
ROLLBACK TRANSACTION 
END CATCH 
+2

hãy cẩn thận với nhật ký giao dịch được điền đầy đủ, v.v. nếu bạn đang chèn nhiều hàng. –

0

Hãy thử đặt nó bên trong giao dịch do người dùng xác định và xem điều gì sẽ xảy ra. Trên thực tế nó nên quay trở lại như bạn mô tả nó.

2

Như đã nêu trong định nghĩa BATCHSIZE cho INSERT RỜI trong MSDN Library (http://msdn.microsoft.com/en-us/library/ms188365(v=sql.105).aspx):

" Nếu điều này không thành công, SQL Server cam kết hoặc cuộn lại giao dịch cho mỗi lô ... "

Kết luận là không cần thiết để thêm giao dịch vào Chèn hàng loạt.

+0

[Tài liệu Microsoft suckzz !!] (http://technet.microsoft.com/es-es/library/ms188365.aspx) Hai ngày thử nghiệm và cuối cùng tôi đã lưu ý rằng BULK INSERT không hỗ trợ rollback trên một lỗi giao dịch cấp biên dịch. Tôi có nghĩa là bạn cần phải tạo một thủ tục lưu trữ cho truy vấn chèn số lượng lớn, sau đó bao quanh exec your_procedure với "try/catch". Cũng rất quan trọng là định nghĩa MAXERRORS = 0 để bắt lỗi đầu tiên ngay lập tức. –

2

Bạn có thể khôi phục các phụ trang. Để làm được điều đó chúng ta cần phải hiểu hai điều đầu tiên

BatchSize

: Không có hàng để được chèn vào mỗi giao dịch. Mặc định là toàn bộ Tệp Dữ liệu. Vì vậy, tệp dữ liệu nằm trong giao dịch

Giả sử bạn có tệp văn bản có 10 hàng và hàng 8 và Hàng 7 có một số chi tiết không hợp lệ. Khi bạn chèn số lượng lớn tệp mà không chỉ định hoặc chỉ định kích thước lô, 8 trong số 10 được chèn vào bảng. Hàng không hợp lệ thứ 8 và thứ 7 bị lỗi và không được chèn vào.

Điều này xảy ra vì số lượng mặc định MAXERRORS là 10 cho mỗi giao dịch.

Như Per MSDN:

MAXERRORS:

Chỉ định số lượng tối đa các lỗi cú pháp cho phép trong các dữ liệu trước khi phẫu thuật với số lượng lớn nhập khẩu bị hủy. Mỗi hàng không thể là được nhập bằng thao tác nhập số lượng lớn sẽ bị bỏ qua và được tính là một lỗi . Nếu max_errors không được xác định, mặc định là 10.

Vì vậy Inorder thất bại tất cả các 10 dòng ngay cả khi một là không hợp lệ chúng ta cần phải thiết lập MAXERRORS=1BatchSize=1 Ở đây số lượng BatchSize cũng có vấn đề.

Nếu bạn chỉ định BatchSize và hàng không hợp lệ nằm trong lô cụ thể, nó sẽ chỉ quay lại lô cụ thể, chứ không phải toàn bộ tập dữ liệu. Vì vậy, hãy cẩn thận khi chọn tùy chọn này

Hy vọng điều này sẽ giải quyết được vấn đề.

+0

Điểm BatchSize = 1 thay vì có câu lệnh INSERT riêng lẻ là gì? – proteus

+0

Tôi nghĩ rằng với kích thước lô = 1 cam kết giao dịch giống như câu lệnh chèn riêng lẻ nhưng sau đó cần một số vòng lặp và số hàng để chèn mà không trùng lặp. Đồng ý với tuyên bố của bạn nhưng nó có thể được thực hiện với sự trợ giúp của các thuộc tính BULK INSERT –

Các vấn đề liên quan