Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

SQL Server 2005 Lỗi 701 - hết bộ nhớ

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:

  1. 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ằng GO . Đâ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.

  2. 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ột BEGIN TRAN / COMMIT TRAN khối.

  3. 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ụng OPENROWSET , 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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hướng dẫn phân vùng và phân vùng bảng SQL Server

  2. Làm thế nào để sử dụng lại một cách chính xác và hiệu quả một câu lệnh đã chuẩn bị trong C # .NET (SQL Server)?

  3. Chuyển đổi kết quả dọc thành chế độ ngang (T-SQL)

  4. Xoay vòng và dấu phẩy Giá trị được phân tách

  5. Thay đổi cột bảng để chấp nhận thêm ký tự