Mô phỏng chuỗi TSQL thông qua thủ tục được lưu trữ


17

Tôi có một yêu cầu để tạo một thủ tục được lưu trữ mô phỏng chuỗi TSQL. Đó là nó luôn cung cấp một giá trị nguyên khác biệt ngày càng tăng trên mỗi cuộc gọi. Ngoài ra, nếu một số nguyên được truyền vào, nó sẽ trả về giá trị đó nếu chưa bao giờ có kết quả lớn hơn hoặc số nguyên cao nhất tiếp theo khả dụng. Không cần phải nói có thể có nhiều khách hàng gọi SP này cùng một lúc.

Đưa ra một bảng MetaInfo với các cột MetaKey varchar (max) và MeatValueLong bigInt. Dự kiến ​​hàng có MetaKey của 'Internal-ID-Last' sẽ chứa giá trị cao nhất được gán cuối cùng. Tôi đã tạo các thủ tục được lưu trữ sau đây:

CREATE PROCEDURE [dbo].[uspGetNextID]
(
  @inID bigInt 
)
AS
BEGIN
    SET NOCOUNT ON;

    BEGIN TRANSACTION

    UPDATE MetaInfo WITH (ROWLOCK) 
      SET MetaValueLong = CASE 
                            WHEN ISNULL(MetaValueLong,0) > @inID THEN MetaValueLong+1 
                            ELSE @inID+1
                          END 
    WHERE MetaKey = 'Internal-ID-Last'

    SELECT MetaValueLong 
    FROM MetaInfo
    WHERE MetaKey = 'Internal-ID-Last'

    COMMIT TRANSACTION 

END

Câu hỏi của tôi chỉ đơn giản là, thủ tục được lưu trữ này có hoạt động như mong đợi không (tất cả người gọi sẽ được chỉ định một kết quả duy nhất)?


@all: FYI, được sinh ra bởi Q này trên SO: stackoverflow.com/q/6342732/27535
gbn

Câu trả lời:


8

Tôi đã có một cái nhìn và MS tự cung cấp một giải pháp không có khóa

http://bloss.msdn.com/b/sqlcat/archive/2006/04/10/sql-server- resultence-number.aspx

Đây là một bản cập nhật đơn giản không có gợi ý khóa, nhưng họ nói rằng nó khóa / khóa chết.

Không có gì nhiều về SO về điều này cả.

Tôi có xu hướng thêm UPDLOCK vào ROWLOCK của bạn (theo "bảng dưới dạng hàng đợi" (SO) nhưng không có READPAST). Điều này sẽ tăng sự cô lập trong trường hợp quy trình thứ 2 bắt đầu đọc.

Tuy nhiên, thực tế tất cả các quy trình của bạn muốn đọc / ghi cùng một hàng khiến tôi lần thứ hai tự đoán. READPAST cho phép đồng thời an toàn nhưng trong trường hợp này nó vô dụng.

Lưu ý: bạn có thể sử dụng mệnh đề OUTPUT thay vì lựa chọn thứ 2 thì bạn không cần giao dịch.

HTH ...


1
Bạn đánh bại tôi vào nó. Lưu ý rằng SQL Server 2011 bao gồm chức năng SEQUENCE, do đó, yêu cầu phát minh của riêng bạn sẽ sớm biến mất (không phải trước thời gian).
nvogel

@dportas: thực sự. Và cũng chạy tốt hơn: dba.stackexchange.com/q/1635/630
gbn

@dportas - SEQUENCE có thể cho phép yêu cầu đầu vào không? Trong phần đọc nhanh của tôi về tính năng tôi không thấy chức năng đó.
Hogan

1

Điều còn thiếu

1. SET XACT_ABORT
2. Exception Handling (Try Catch)

Vâng, nó sẽ đáp ứng điều kiện của bạn. Khi các tình huống như vậy xảy ra trong các giao dịch, Nó tạo ra nhiều trường hợp và sau đó, tất cả người gọi sẽ được chỉ định một kết quả duy nhất


Nếu tôi cam kết trước khi chọn không có khả năng tôi sẽ chọn kết quả được lưu bởi một cuộc gọi khác?
Hogan

Không chắc chắn về nó. Nhưng có vẻ như bạn đúng. Tôi cần phải kiểm tra. Cảm ơn. BTW +1 cho, Câu hỏi hay ...

0

Một giải pháp có thể mở rộng hơn mà không yêu cầu tuần tự hóa là:

CREATE PROCEDURE [dbo].[uspGetNextID]
(
  @inID BIGINT OUT
)
AS
      SET NOCOUNT ON
      SET IDENTITY_INSERT SequenceTable ON;
      INSERT INTO SequenceTable (id) VALUES (@inID);
      SET IDENTITY_INSERT SequenceTable OFF;
      INSERT INTO SequenceTable DEFAULT VALUES;
      DELETE FROM SequenceTable WITH (READPAST);
      SET @inID = SCOPE_IDENTITY();
RETURN;

OP có một yêu cầu cho phép người dùng vượt qua một giá trị làm phức tạp nó ...
gbn

@dportas - Cảm ơn. Tôi đã biết về cách tiếp cận này, nhưng nó không hoạt động ở đây vì tham số đầu vào.
Hogan

@Hogan, tôi đã sửa đổi đề xuất của mình để xử lý tham số đầu vào. Nó hầu như chưa được kiểm tra.
nvogel

@dportas - A được gọi với inID là 500, B được gọi với inID là 50 - hành động - A trả về với 51, B với 52. Yêu cầu thất bại.
Hogan

Hấp dẫn. Tôi nhận được kết quả khác nhau (trên 2008r2). Bạn có thể đăng toàn bộ repro với DDL và nêu bản dựng / phiên bản của bạn.
nvogel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.