2011-01-31 33 views
6

Tôi đang xử lý một bảng trong SQL Server có cột serial_no, được định nghĩa là int không null. Nó dường như không phải là trường tăng tự động, như thể tôi để cột đó ra khỏi câu lệnh chèn của tôi, tôi nhận được một lỗi nói rằng trường serial_no không thể rỗng.Máy chủ SQL: chèn tiếp theo có sẵn int

Vậy làm cách nào để chèn số sẵn có tiếp theo?

Tôi cố gắng này:

INSERT INTO mytable (serial_no) VALUES ((SELECT MAX(serial_no)+1 FROM mytable)) 

nhưng tôi nhận được một thông báo lỗi rằng các truy vấn con không thể được sử dụng trong bối cảnh này.

EDIT: Bảng này được sử dụng trong sản phẩm ngoài giá để tôi không thể thay đổi thiết kế và làm cho cột serial_no tăng tự động.

+0

Nó có phải là duy nhất trên tất cả các hàng không ?? Các phương pháp được đề xuất trong các câu trả lời thường không an toàn đồng thời, ví dụ: bạn có thể kết thúc với bản sao ..... bạn hoặc cần phải a) làm cho điều này một cột 'INT IDENTITY' và để cho SQL Server lo lắng về nó, b) làm nhiều công việc hơn so với obviuos' SELECT MAX (serial_no) + 1', hoặc c) chờ cho SQL Server 2011 và sử dụng khái niệm 'SEQUENCES' –

+0

marc_s, tôi hoàn toàn đồng ý, nhưng tiếc là tôi không thể thay đổi thiết kế DB. Điều gì xảy ra nếu tôi khóa bàn, hãy lắp và mở khóa? Điều đó có bảo vệ nó khỏi việc tạo ra một bản dupe không? Hoặc một truy vấn đang chờ đợi chỉ cần chờ khóa để giải phóng và sau đó chèn một bản sao # anyway? –

+1

Bạn có thể chạy một dấu vết để xác định cách ứng dụng của bên thứ ba tạo giá trị và chỉ làm như vậy không? Tôi sẽ nói rằng nếu không có một cột nhận dạng họ có khả năng sử dụng một bảng để giữ giá trị tiếp theo. Có một câu trả lời đã đề cập đến kỹ thuật này rồi. –

Trả lời

9

Bạn có thể cải thiện ghi đồng thời với khóa gợi ý

INSERT INTO mytable (serial_no, value) 
SELECT MAX (serial_no)+1, @value 
FROM mytable WITH (ROWLOCK, XLOCK, HOLDLOCK) 

Nếu hiệu suất is't quan trọng, hãy thử TABLOCKX ở vị trí của cột chèo, XLOCK

Tuy nhiên, do đây không phải là an toàn hoặc là bạn cần phải thử lại

DECLARE @retry bit 
SET @retry = 1 

WHILE @Retry = 1 
BEGIN 
    BEGIN TRY 
     INSERT INTO mytable (serial_no, value) 
     SELECT MAX (serial_no)+1, @value 
     FROM mytable WITH (ROWLOCK, XLOCK, HOLDLOCK) 

     SET @Retry = 0 
    END TRY 
    BEGIN CATCH 
     IF ERROR_NUMBER() <> 2627 --PK violation 
      RAISERROR ('blah', 16, 1) 
    END CATCH 
END 

Hoặc chuyển sang một cột IDENTITY và làm đúng cách ...

+1

+1, mặc dù dòng cuối cùng của bạn phải ở dạng ** in đậm ** thực sự. – cjk

+0

danh tính là sự lựa chọn tốt nhất khi có thể. Tuy nhiên, có những trường hợp cần có khóa duy nhất được quản lý theo cách thủ công. Điều này xảy ra là trường hợp tôi đang ở. Một khách hàng muốn một FileNumber duy nhất, đó là tuần tự, người dùng có thể chỉnh sửa, và thay đổi sự bắt đầu của chuỗi mỗi năm – George

+0

@George: bây giờ chúng ta có chuỗi trong SQL Server 2012 fro loại công cụ này – gbn

2

Các lỗi có thể được sửa chữa bằng cách thả các GIÁ TRỊ

INSERT INTO mytable (serial_no, value) 

SELECT MAX(serial_no)+1 , 
@value 
FROM mytable) 

Nhưng đây là một ý tưởng tồi. Có điều kiện chủng tộc trên MAX (serial_no) +1 (ví dụ: hai Phụ trang có cùng giá trị cho Max (Serial_no)

Bạn nên sử dụng trường tăng tự động. Bạn cũng có thể tạo bảng lưu trữ hiện tại giá trị tiếp theo và tăng nó thay vì sử dụng tối đa

+1

+1 để đề cập đến khả năng trùng lặp với phương pháp MAX() + 1 này; và đề xuất giải pháp tăng tự động –

+0

Vấn đề là nó không phải là bảng hoặc ứng dụng của tôi. Tôi không thể thay đổi nó. –

0
INSERT INTO mytable (serial_no) SELECT MAX(serial_no)+1 FROM mytable 
+1

không an toàn - có thể kết thúc với các bản sao, nếu hai INSERT xảy ra từ hai kết nối cùng lúc .... –

0

Hãy thử nó không có giá trị:.

INSERT INTO mytable (serial_no) SELECT MAX(serial_no)+1 FROM mytable 
+0

không an toàn - có thể kết thúc với các bản sao, nếu hai INSERT xảy ra từ hai kết nối tại cùng một thời điểm. .. –

+0

Vâng ... Giải pháp xấu xí ở đây sẽ là chạy chèn trong giao dịch ... –

+2

không xấu - giải pháp ** duy nhất và an toàn **! –

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