Meniru urutan TSQL melalui prosedur tersimpan

17

Saya memiliki persyaratan untuk membuat prosedur tersimpan yang mengemulasi urutan TSQL. Itu selalu memberikan peningkatan nilai integer yang berbeda pada setiap panggilan. Selain itu, jika bilangan bulat dilewatkan di dalamnya harus mengembalikan nilai itu jika tidak pernah ada hasil yang lebih besar atau bilangan bulat tertinggi berikutnya yang tersedia. Tak perlu dikatakan bahwa ada beberapa klien yang memanggil SP ini pada saat yang sama.

Diberikan tabel MetaInfo dengan kolom MetaKey varchar (max) dan MeatValueLong bigInt. Diharapkan baris dengan MetaKey 'Internal-ID-Last' akan berisi nilai tertinggi terakhir yang diberikan. Saya membuat prosedur tersimpan berikut:

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

Pertanyaan saya sederhana, apakah prosedur tersimpan ini berfungsi seperti yang diharapkan (semua penelepon akan diberikan hasil yang unik)?

Hogan
sumber
@all: FYI, muncul dengan Q ini di SO: stackoverflow.com/q/6342732/27535
gbn

Jawaban:

8

Saya sudah pernah melihat dan MS sendiri menawarkan solusi tanpa kunci

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

Ini adalah pembaruan sederhana tanpa petunjuk kunci, tetapi mereka mengatakan itu mengunci / deadlock.

Tidak banyak tentang SO tentang ini juga.

Saya akan cenderung menambahkan UPDLOCK ke ROWLOCK Anda (sesuai "tabel sebagai antrian" (SO) tetapi tanpa READPAST). Ini akan meningkatkan isolasi jika proses kedua mulai membaca.

Namun, faktanya semua proses Anda ingin membaca / menulis baris yang sama membuat saya menebak sendiri. READPAST memungkinkan konkurensi yang aman tetapi dalam kasus ini tidak berguna.

Catatan: Anda dapat menggunakan klausa OUTPUT alih-alih memilih ke-2 maka Anda tidak perlu transaksi.

HTH ...

gbn
sumber
1
Anda mengalahkan saya untuk itu. Perhatikan bahwa SQL Server 2011 menyertakan fungsionalitas SEQUENCE sehingga persyaratan untuk membuat Anda sendiri harus segera dihapus (tidak sebelum waktu).
nvogel
@dportas: memang. Dan berjalan lebih baik juga: dba.stackexchange.com/q/1635/630
gbn
@dportas - bisakah SEQUENCE mengizinkan persyaratan input? Dalam membaca cepat saya tentang fitur saya tidak melihat fungsi itu.
Hogan
1

Hal-hal berikut hilang

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

Ya, itu harus memenuhi kondisi Anda. Setelah situasi seperti itu terjadi dalam transaksi, itu menciptakan beberapa contoh dan selanjutnya, semua penelepon akan diberikan hasil yang unik

Pankaj
sumber
Jika saya komit sebelum pilih, apakah tidak ada kemungkinan saya akan memilih hasil yang disimpan oleh panggilan yang berbeda?
Hogan
Tidak yakin tentang itu. Tapi sepertinya kamu benar. Saya perlu memeriksa. Terima kasih. BTW +1 untuk, Pertanyaan Bagus ...
0

Solusi yang lebih scalable yang tidak memerlukan serialisasi adalah ini:

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;
nvogel
sumber
OP memiliki persyaratan untuk memungkinkan pengguna memberikan nilai yang menyulitkannya ...
gbn
@dportas - Terima kasih. Saya mengetahui pendekatan ini, tetapi tidak berfungsi di sini karena parameter input.
Hogan
@Hogan, saya telah memodifikasi saran saya untuk menangani parameter input. Namun sebagian besar belum teruji.
nvogel
@dportas - A dipanggil dengan ID 500, B disebut dengan ID 50 - aksi - A kembali dengan 51, B dengan 52. Persyaratan gagal.
Hogan
Menarik. Saya mendapatkan hasil yang berbeda (pada 2008r2). Bisakah Anda memposting repro lengkap dengan DDL dan menyatakan versi / build Anda.
nvogel