Емуляція послідовності TSQL за допомогою збереженої процедури


17

У мене є вимога створити збережену процедуру, яка імітує послідовність TSQL. Тобто воно завжди дає все більше зростаюче ціле значення для кожного виклику. Крім того, якщо введено ціле число, воно повинно повернути це значення, якщо ніколи не було результату більше або наступне найвище ціле число. Само собою зрозуміло, що може бути декілька клієнтів, які дзвонять цим ІП одночасно.

Дано таблицю MetaInfo зі стовпчиками MetaKey varchar (max) та MeatValueLong bigInt. Очікується, що рядок з MetaKey 'Internal-ID-Last' буде містити останнє найвище значення, призначене. Я створив таку збережену процедуру:

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

Моє запитання просто, чи працює ця збережена процедура як очікувалося (всім абонентам буде призначений унікальний результат)?


@all: FYI, породжені цією Q на SO: stackoverflow.com/q/6342732/27535
GBN

Відповіді:


8

Я придивився, і самі MS пропонують рішення без замків

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

Це просте оновлення без натяків на блокування, але вони кажуть, що це блокування / тупики.

З цього приводу теж нічого не буває.

Я б схильний додати UPDLOCK до вашого ROWLOCK (відповідно до "таблиці як черги" (SO), але без READPAST). Це збільшить ізоляцію, якщо другий процес почне читання.

Однак той факт, що всі ваші процеси хочуть читати / писати в одному рядку, змушує мене другий здогад. READPAST дозволяє отримати безпечну сумісність, але в цьому випадку вона марна.

Примітка: ви можете використовувати пункт OUTPUT замість другого вибору, тоді транзакція вам не потрібна.

HTH ...


1
Ти побив мене до цього. Зауважте, що SQL Server 2011 включає функціональність SEQUENCE, тому вимога винайти власну повинна скоротитись (не раніше часу).
nvogel

@dportas: справді. І працює також краще: dba.stackexchange.com/q/1635/630
gbn

@dportas - чи SEQUENCE може дозволити вимогу введення? Під час швидкого читання функції я не бачив цієї функціональності.
Хоган

1

Наступна річ відсутня

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

Так, це повинно відповідати вашій умові. Як тільки подібні ситуації трапляються в транзакціях, він створює кілька примірників, і згодом всім абонентам буде призначений унікальний результат


Якщо я покладу зобов'язання перед вибором, чи не існує можливості, я виберу результат, збережений іншим викликом?
Хоган

Не впевнений у цьому. Але здається, ти маєш рацію. Мені потрібно перевірити. Спасибі. BTW +1 за, гарне запитання ...

0

Більш масштабоване рішення, яке не потребує серіалізації:

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;

ОП має вимогу дозволити користувачам передавати значення, яке його ускладнює ...
gbn

@dportas - Дякую Мені було відомо про цей підхід, але він не працює тут через вхідний параметр.
Хоган

@Hogan, я змінив свою пропозицію обробляти вхідний параметр. Це, головним чином, неперевірене.
nvogel

@dportas - Виклик з inID 500, B викликається inID 50 - дія - A повертається з 51, B з 52. Вимога не відповідає.
Хоган

Цікаво. Я отримую різні результати (на 2008р2). Чи можете ви опублікувати повне запитання з DDL та вказати свою збірку / версію.
nvogel
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.