Последовательность Microsoft SQL Server 2014

Краткое описание, я создаю программу VB.NET с нуля, включая базу данных. Поэтому мне необходимо установить уникальный идентификатор транзакции для каждой таблицы, например header_id, detail_id, order_number и многие другие, для которых требуется любое текущее число приращения. Я обновляюсь с SQL Server 2005 до SQL Server 2014, чтобы иметь встроенный SEQUENCE для работы с текущими номерами.

Моя текущая ситуация (SQL Server 2005, VB.NET): я использую таблицу для хранения всех текущих номеров и хранимую процедуру для выполнения текущих номеров из моей программы VB.NET. Например, в Sales Order я передам жестко запрограммированный параметр хранимой процедуре, чтобы найти значение в таблице, затем увеличу число на 1, а затем вставлю его в таблицу Sales Order.

Прежде чем я начну миграцию базы данных и изменение структуры таблиц, я хотел бы знать, правильно ли я начал, что означает, что для каждой таблицы я должен назначить для нее определенную последовательность? Пожалуйста, направляйте.


person 4 Leave Cover    schedule 13.07.2015    source источник
comment
Не совсем понятно, почему вы считаете, что должны сами выбирать уникальные идентификаторы, а не возлагать эту задачу на СУБД. Даже в SQL Server 2005 можно было использовать столбцы IDENTITY и/или UNIQUEIDENTIFIER... знаете ли вы об этом?   -  person stakx - no longer contributing    schedule 13.07.2015
comment
Привет, stakx, я никогда не имел дело ни со столбцами IDENTITY, ни с UNIQUEIDENTIFIER. Вы не против пролить свет?   -  person 4 Leave Cover    schedule 13.07.2015


Ответы (1)


Обычно вам не нужен SEQUENCE для создания уникальных повышающихся значений идентификаторов для отдельных таблиц. Даже с SQL Server 2005 у вас есть два более простых варианта:

  1. Определите столбец IDENTITY. Например:

    CREATE TABLE Orders
    (
        OrderId INT IDENTITY(1,1) NOT NULL,
        …        -- ^^^^^^^^^^^^^
    );           -- very much like an unnamed sequence that START WITH 1 INCREMENT BY 1
    

    При INSERT входе в эту таблицу вам не нужно указывать значение для OrderId, оно будет выбрано за вас СУБД. Полученные идентификаторы будут уникальными (но возможны пробелы).

  2. Вместо использования целочисленных идентификаторов используйте идентификаторы GUID:

    CREATE TABLE Orders
    (
        OrderId UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL DEFAULT (NEWSEQUENTIALID()),
        …
    );
    

    Ограничение DEFAULT означает, что вам не нужно явно выбирать значение для OrderId при INSERT; РСУБД сгенерирует для вас значение.

    P.S.: NEWSEQUENTIALID() гарантирует, что генерируемые идентификаторы GUID неуклонно растут. Это важно, если столбец GUID используется для кластеризации (т. е. когда у вас есть ограничение PRIMARY KEY CLUSTERED (OrderId ASC)), как указано в комментарий ниже. Если столбец не используется для кластеризации и важно только, чтобы идентификаторы GUID были уникальными, но не обязательно увеличивались, вместо этого можно также использовать NEWID().

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

CREATE SEQUENCE OrderIds START WITH 1 INCREMENT BY 1;

CREATE TABLE FlowerOrders
(
    OrderId INT NOT NULL DEFAULT (NEXT VALUE FOR OrderIds),
    …
);

CREATE TABLE FlowerPotOrders
(
    OrderId INT NOT NULL DEFAULT (NEXT VALUE FOR OrderIds)
    …
);

Таким образом, должно быть невозможно, чтобы FlowerOrders и FlowerPotOrders содержали перекрывающиеся OrderId.

person stakx - no longer contributing    schedule 13.07.2015
comment
В моем случае у меня есть несколько таблиц, связанных с идентификаторами. Например, таблица order_header и table order_detail и связь основана на столбце header_id в обеих таблицах. - person 4 Leave Cover; 13.07.2015
comment
При использовании UNIQUEIDENTIFIER и ограничения по умолчанию я настоятельно рекомендую использовать функцию newsequentialid() по умолчанию, особенно если этот столбец GUID может оказаться ключом кластеризации. - person marc_s; 13.07.2015
comment
@4LeaveCover: ограничения внешнего ключа не имеют ничего общего со способами гарантировать уникальность первичных ключей… Вопрос: вы знаете, что такое ограничения FOREIGN KEY? - person stakx - no longer contributing; 13.07.2015
comment
Это отношения 1:1? - person Zohar Peled; 13.07.2015
comment
@marc_s: Ты прав. Я добавил примечание к своему ответу об этом. Я часто использую другой подход: у меня может быть два столбца идентификаторов в моих таблицах, один (внутренний в БД) INT IDENTITY (который является ключом кластеризации и принимает участие в отношениях между первичным и внешним ключами). ) и индексированный UNIQUEIDENTIFIER ROWGUIDCOL (какие приложения могут выбирать сами и по которым они могут искать записи). - person stakx - no longer contributing; 13.07.2015
comment
@stakx Мне нужен так называемый «transaction_id» в моей таблице, он должен быть только читаемым числовым значением и должен быть уникальным в таблице. Мне нужно будет запросить данные на основе этого конкретного transaction_id. Поэтому, по-вашему, я должен использовать INT IDENTITY? - person 4 Leave Cover; 13.07.2015
comment
тогда вам нужен уникальный идентификатор для каждой таблицы, но не уникальный идентификатор, который будет распространяться на несколько таблиц. В этом случае используйте простой вариант идентификации int (первый в этом ответе). - person Zohar Peled; 13.07.2015
comment
@4LeaveCover: transaction_id также будет первичным ключом в этой таблице? Если это так, применяется первый пример кода в моем ответе (за исключением того, что вам также необходимо объявить столбец PRIMARY KEY). Если нет, то вам, возможно, действительно придется прибегнуть к SEQUENCE… если вы не хотите переосмыслить дизайн схемы вашей базы данных: вы можете настроить отдельную таблицу transactions, где transaction_id — это IDENTITY и PRIMARY KEY, а другие ваши таблицы ссылаются на нее через отношение внешнего ключа). - person stakx - no longer contributing; 13.07.2015
comment
@stakx С этого момента я изменю каждую таблицу, чтобы она имела ИДЕНТИФИКАЦИЮ. Но для случая, когда отношения 1:many, например, у меня есть header_id (IDENTITY) и order_number в таблице order_header, я передам order_number в таблицу order_detail, поэтому ключ отношения — это order_number. Таблица order_detail будет иметь свой собственный detail_id (IDENTITY), но только для целей транзакции. Верен ли мой подход? - person 4 Leave Cover; 13.07.2015
comment
@4LeaveCover: обратите внимание, что это превращается в совершенно другой вопрос. Если вам нужна помощь в определении отношений внешнего ключа, задайте отдельный вопрос. Спасибо! - person stakx - no longer contributing; 13.07.2015