SQL Server 2005 - используя сгенерированные последовательности вместо столбцов идентификаторов? - PullRequest
1 голос
/ 22 февраля 2011

Я действительно думаю о том, чтобы перейти от столбцов Identity в SQL Server 2005 и перейти к какому-то типу генератора последовательностей (насколько я знаю, в 2005 году нет ничего встроенного, чтобы сделать это; может быть, в 2011?) получить уникальные идентификаторы для вставленных строк.

Есть ли реализация модели или лучшая практика для этого? Буду ли я сталкиваться с проблемами блокировки? Каковы недостатки по сравнению только с использованием столбцов Identity?

Ответы [ 2 ]

5 голосов
/ 23 февраля 2011

Да, в SQL 11 есть объекты SEQUENCE, см. SQL Server v.Next (Denali): Использование SEQUENCE .

Создание ручных последовательностей возможно, но не рекомендуется. Хитрость в создании генератора последовательностей заключается в использовании UPDATE WITH OUTPUT в таблице последовательностей. Вот псевдокод:

CREATE TABLE Sequences (
    Name sysname not null primary key, 
    Sequence bigint not null default 0);
GO

CREATE PROCEDURE sp_getSequence
    @name sysname,
    @value bigint output
AS
    UPDATE Sequences
    SET Sequence = Sequence + 1
     OUTPUT @value = INSERTED.Sequence
    WHERE Name = @name;
GO

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

Я бы предпочел, чтобы вы придерживались типов IDENTITY. Хотя они и не идеальны, они намного лучше, чем вы можете достичь самостоятельно.

1 голос
/ 28 августа 2013

Для решения этой проблемы я использовал таблицу «Последовательности», в которой хранятся все мои последовательности, и хранимую процедуру «nextval».

Таблица Sql:

CREATE TABLE Sequences (  
    name VARCHAR(30) NOT NULL,  
    value BIGINT DEFAULT 0 NOT NULL,  
    CONSTRAINT PK_Sequences PRIMARY KEY (name)  
);

PK_Sequence используется только для того, чтобы быть уверенным, что никогда не будет последовательностей с одинаковым именем.

Sql хранимая процедура:

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'nextVal') AND type in (N'P', N'PC')) DROP PROCEDURE nextVal;  
GO  
CREATE PROCEDURE nextval  
    @name VARCHAR(30)  
AS  
    BEGIN  
        DECLARE @value BIGINT  
        BEGIN TRANSACTION  
            UPDATE Sequences  
            SET @value=value=value + 1  
            WHERE name = @name;  
            -- SELECT @value=value FROM Sequences WHERE name=@name  
        COMMIT TRANSACTION  
        SELECT @value AS nextval  
    END;  

Вставьте несколько последовательностей:

INSERT INTO Sequences(name, value) VALUES ('SEQ_Workshop', 0);
INSERT INTO Sequences(name, value) VALUES ('SEQ_Participant', 0);
INSERT INTO Sequences(name, value) VALUES ('SEQ_Invoice', 0);  

Наконец получите следующее значение последовательности,

execute nextval 'SEQ_Participant';  

Somec # код для получения следующего значения из таблицы Sequence,

public long getNextVal()
{
    long nextval = -1;
    SqlConnection connection = new SqlConnection("your connection string");
    try
    {
        // Connect and execute the select sql command.
        connection.Open();

        SqlCommand command = new SqlCommand("nextval", connection);
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.Add("@name", SqlDbType.NVarChar).Value = "SEQ_Participant";
        nextval = Int64.Parse(command.ExecuteScalar().ToString());

        command.Dispose();
    }
    catch (Exception) { }
    finally
    {
        connection.Dispose();
    }
    return nextval;
}  
...