Генераторы последовательностей в T-SQL - PullRequest
2 голосов
/ 27 февраля 2009

У нас есть приложение Oracle, которое использует стандартный шаблон для заполнения суррогатных ключей. У нас есть ряд внешних строк (которые имеют определенные значения для суррогатных ключей) и другие строки, которые имеют внутренние значения. Мы используем следующий фрагмент триггера Oracle, чтобы определить, что делать с суррогатным ключом при вставке:

IF :NEW.SurrogateKey IS NULL THEN

 SELECT SurrogateKey_SEQ.NEXTVAL INTO :NEW.SurrogateKey FROM DUAL;

END IF;

Если предоставленный суррогатный ключ равен нулю, получить значение из назначенной последовательности, иначе передать указанный суррогатный ключ в строку.

Кажется, я не могу найти простой способ сделать это с помощью T-SQL. Есть все виды подходов, но ни один из них не использует понятие генератора последовательностей, как Oracle и другие совместимые с SQL-92 БД.

Кто-нибудь знает действительно эффективный способ сделать это в SQL Server T-SQL? Кстати, мы используем SQL Server 2008, если это поможет.

Ответы [ 3 ]

2 голосов
/ 27 февраля 2009

Вы можете посмотреть на IDENTITY. Это дает вам столбец, для которого будет определено значение при вставке строки.

Это может означать, что вам нужно вставить строку и определить значение впоследствии, используя SCOPE_IDENTITY ().

Здесь также есть статья о моделировании последовательностей Oracle в SQL Server: http://www.sqlmag.com/Articles/ArticleID/46900/46900.html?Ad=1

0 голосов
/ 26 июля 2010

Вот способ сделать это, используя таблицу для хранения вашего последнего порядкового номера. Хранимый процесс очень прост, большинство вещей там, потому что я ленив и не люблю сюрпризов, если я что-то забуду так ... вот оно:

----- Создать таблицу значений последовательности.

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[SequenceTbl]
(
  [CurrentValue] [bigint]
) ON [PRIMARY]

GO

----------------- Создать хранимую процедуру

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE procedure [dbo].[sp_NextInSequence](@SkipCount BigInt = 1)
AS

BEGIN

  BEGIN TRANSACTION

    DECLARE @NextInSequence BigInt;

    IF NOT EXISTS
    (
      SELECT
        CurrentValue
      FROM
        SequenceTbl
    )

    INSERT INTO SequenceTbl (CurrentValue) VALUES (0);

    SELECT TOP 1
      @NextInSequence = ISNULL(CurrentValue, 0) + 1
    FROM
      SequenceTbl WITH (HoldLock);

    UPDATE SequenceTbl WITH (UPDLOCK)
      SET CurrentValue = @NextInSequence + (@SkipCount - 1);

  COMMIT TRANSACTION

  RETURN @NextInSequence
END;
GO

-------- Используйте хранимую процедуру в Sql Manager, чтобы получить тестовое значение.

declare @NextInSequence BigInt

exec @NextInSequence = sp_NextInSequence;

--exec @NextInSequence = sp_NextInSequence <skipcount>;

select NextInSequence = @NextInSequence;

----- Показать текущее значение таблицы.

select * from SequenceTbl;

Проницательный заметит, что для сохраненного процесса есть параметр (необязательный). Это позволяет вызывающему абоненту зарезервировать блок идентификаторов в том случае, если у вызывающего абонента имеется более одной записи, для которой требуется уникальный идентификатор - при использовании SkipCount вызывающему абоненту необходимо сделать только один вызов для любого количества идентификаторов. Весь блок «IF EXISTS ... INSERT INTO ...» можно удалить, если вы не забыли вставить запись при создании таблицы. Если вы также не забыли вставить эту запись со значением (ваше начальное значение - число, которое никогда не будет использоваться в качестве идентификатора), вы также можете удалить часть выбора ISNULL (...) и просто использовать CurrentValue + 1. Теперь, прежде чем кто-либо сделает комментарий, пожалуйста, обратите внимание, что я инженер-программист, не DBA! Итак, любая конструктивная критика в отношении использования «Top 1», «With (HoldLock)» и «With (UPDLock)» приветствуется. Я не знаю, насколько хорошо это будет масштабироваться, но пока у меня все в порядке ...

0 голосов
/ 27 февраля 2009

Идентификация - это один из подходов, хотя он генерирует уникальные идентификаторы на уровне таблицы.

Другой подход заключается в использовании уникальных идентификаторов, в частности с использованием NewSequantialID (), который следует, что сгенерированный идентификатор всегда больше, чем последний. Проблема этого подхода в том, что вы больше не имеете дело с целыми числами.

Ближайший способ эмулировать метод oracle - создать отдельную таблицу с полем счетчика, а затем написать пользовательскую функцию, которая запрашивает это поле, увеличивает его и возвращает значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...