Câu hỏi này thực sự xuất hiện thường xuyên ở đây. Đánh dấu có câu trả lời chính xác (và được tuyển dụng phổ biến nhất), nhưng hãy để tôi cố gắng bổ sung những gì có thể để làm rõ ràng hơn.
Thông báo lỗi là một chút sai lầm. SQL Server cho bạn biết rằng nó không có đủ bộ nhớ để chạy truy vấn, nhưng ý nghĩa thực sự là nó không có đủ bộ nhớ để phân tích cú pháp truy vấn.
Khi nói đến đang chạy truy vấn, SQL Server có thể sử dụng tất cả những gì nó muốn - gigabyte nếu cần. Phân tích cú pháp là một câu chuyện khác; máy chủ phải xây dựng một cây phân tích cú pháp và chỉ có một lượng bộ nhớ rất hạn chế cho việc đó. Tôi chưa bao giờ tìm thấy giới hạn thực tế được ghi lại ở bất kỳ đâu nhưng đối với một lô điển hình chứa đầy INSERT
, nó không thể xử lý nhiều hơn một vài MB cùng một lúc.
Vì vậy, tôi rất tiếc phải nói với bạn điều này nhưng bạn không thể làm cho SQL Server thực thi tập lệnh này chính xác như nó được viết. Không có cách nào, không có cách nào, không quan trọng bạn điều chỉnh cài đặt nào. Tuy nhiên, bạn có một số tùy chọn để giải quyết vấn đề đó:
Cụ thể, bạn có ba tùy chọn:
-
Sử dụng
GO
các câu lệnh. Điều này được sử dụng bởi SSMS và nhiều công cụ khác như một bộ phân tách hàng loạt. Thay vì một cây phân tích cú pháp duy nhất được tạo cho toàn bộ tập lệnh, các cây phân tích cú pháp riêng lẻ được tạo cho từng phân đoạn của lô được phân tách bằngGO
. Đây là điều mà hầu hết mọi người đều làm và rất đơn giản để vẫn đảm bảo an toàn cho giao dịch tập lệnh, như những người khác đã chứng minh và tôi sẽ không nhắc lại ở đây. -
Thay vì tạo một tập lệnh lớn để chèn tất cả các hàng, hãy giữ dữ liệu trong tệp văn bản (tức là được phân tách bằng dấu phẩy). Sau đó, nhập nó bằng cách sử dụng tiện ích bcp . Nếu bạn cần điều này là "scriptable" - tức là quá trình nhập cần diễn ra trong cùng một tập lệnh / giao dịch với
CREATE TABLE
tuyên bố, sau đó sử dụng CHÈN SỐ LƯỢNG LỚN thay vì. Mặc dùBULK INSERT
là một hoạt động không đăng nhập, tin hay không, nó vẫn có thể được đặt trong mộtBEGIN TRAN
/COMMIT TRAN
khối. -
Nếu bạn thực sự muốn
INSERT
là một hoạt động được ghi lại và không muốn việc chèn diễn ra hàng loạt, thì bạn có thể sử dụng OPENROWSET để mở tệp văn bản, tệp excel, v.v. dưới dạng "bảng" đặc biệt, rồi chèn tệp này vào bảng mới tạo của bạn. Tôi thường không thích bao giờ khuyên bạn nên sử dụngOPENROWSET
, nhưng vì đây rõ ràng là một tập lệnh quản trị, nó không thực sự là một vấn đề lớn.
Các nhận xét trước đây cho thấy rằng bạn không thoải mái với số 1, mặc dù điều đó có thể chỉ là do một giả định không chính xác rằng nó không thể được thực hiện trong một giao dịch duy nhất, trong trường hợp đó, hãy xem Thomas
của câu trả lời. Nhưng nếu bạn không muốn đi theo cách khác, tôi khuyên bạn nên đi với # 2, tạo một tệp văn bản và sử dụng BULK INSERT
. Ví dụ về tập lệnh "an toàn" sẽ là:
BEGIN TRAN
BEGIN TRY
CREATE TABLE MyTable (...)
BULK INSERT MyTable
FROM 'C:\Scripts\Data\MyTableData.txt'
WITH (
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\r\n',
BATCHSIZE = 1000,
MAXERRORS = 1
)
COMMIT
END TRY
BEGIN CATCH
ROLLBACK
END CATCH
Hy vọng rằng điều này sẽ giúp đưa bạn đi đúng hướng. Tôi khá chắc chắn rằng điều này bao gồm tất cả các tùy chọn "trong hộp" có sẵn của bạn - ngoài những tùy chọn này, bạn phải bắt đầu viết các chương trình ứng dụng thực tế hoặc các tập lệnh shell để thực hiện công việc và tôi không nghĩ rằng mức độ phức tạp đó là thực sự được bảo hành ở đây.