Возможные способы иметь AutoNumber для пользователя (или для объекта)? - PullRequest
0 голосов
/ 08 июля 2011

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

Теперь предположим, чтокаждый продавец книг действительно хочет, чтобы с каждой книгой ассоциировался уникальный номер, чтобы они могли искать книги по этому номеру, но для них важно, чтобы число было для них примерно последовательным.(Это нормально, если в последовательности есть небольшие разрывы из-за удаленных книг и других событий, которые приводят к тому, что AutoNumber используется, но не используется).

Очевидно, что каждая книга уже имеет уникальный номер (первичный ключ), связанный сэто то, что генерируется через AutoNumber и является уникальным среди продавцов книг.Это не то, что я обсуждаю здесь.

Давайте просто предположим, что SQL-сервер с этого момента, но обсуждение в равной степени относится к Oracle (за исключением того, что Oracle использует последовательности, которые не зависят от таблиц, и текущей версии SQLСервер должен использовать таблицу, чтобы выполнить то же самое).

Мы хотим, чтобы число безопасно увеличивалось в контексте продавца книг.Мы хотим сохранить преимущества использования AutoNumber, но мы хотим, чтобы для продавца книг была одна последовательность.Кажется, что есть два варианта, и ни один из них не очень хорош:

  1. Создайте одну таблицу из одного столбца на продавца книг.Это пугает меня, потому что я не могу вспомнить другой пример динамического изменения схемы (добавление новой таблицы всякий раз, когда новый продавец книг добавляется в систему через веб-приложение) в веб-запросе.Кроме того, кажется очень тяжелым иметь один стол на одного продавца книг.Я знаю, что будущая версия SQL-сервера будет поддерживать последовательности, но даже это все равно будет изменением схемы во время выполнения.

  2. Сверните свое собственное поведение автоматической нумерации.Это кажется очень рискованным, потому что встроенные в базы данных функции AutoNumber позаботятся о многих вещах для вас, и отказаться от этого - большое дело.Попытки реализовать его самостоятельно, вероятно, подвержены ошибкам и могут привести к худшему параллелизму, чем встроенный AutoNumber.

Надеемся, что мне не хватает дополнительных опций.Кто-нибудь успешно справлялся с подобной ситуацией?Спасибо.

Ответы [ 3 ]

3 голосов
/ 08 июля 2011

Существует ли причина, по которой у вас не было таблицы с 2 полями:

BookSeller_ID, BookID

Вам не нужно менять схему при добавлении продавцов, и отслеживать каждого продавца будет тривиально:

SELECT MAX(BookID)
WHERE BookSeller_ID = 123

Для получения дополнительной информации вы также можете добавить поле Universal_BookID, связанное с вашим уникальным идентификатором, указанным в третьем абзаце.

EDIT:

Чтобы уточнить, если у вас есть продавцы 1, 2 и 3, у вас может быть такая таблица:

SellerID    BookID   BookUniversalID
1           1        123
2           1        456
3           1        999
1           2        1234
1           3        8798
1           4        999
1           5        10000001
3           2        123
3           3        456

Вы отслеживаете, какому продавцу назначены идентификаторы, и какую книгу он тоже связывает, и чтобы определить, каким будет следующий идентификатор продавца, просто запросите

SELECT MAX(bookid) FROM ThisTable WHERE SellerID = 1

2 голосов
/ 08 июля 2011

DENSE_RANK, работает в SQL Server и Oracle

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

CREATE VIEW dbo.BOOK_TO_SELLER_MAP
AS
SELECT
    B.*
,   DENSE_RANK() OVER (PARTITION BY B.seller_id ORDER BY B.internal_book_id ASC) AS unique_book_id_for_seller
FROM
    dbo.BOOKS B
WHERE
    B.seller_id = @sellerId

Для комбинации seller_id и сгенерированного идентификатора вы всегда должны соответствовать истинному идентификатору (при условии отсутствия физического удаления).

Демонстрационный код

;
WITH BOOKS (internal_book_id, seller_id, title)
AS
(
    SELECT 1, 100, 'Secret of NIMH'
    UNION ALL SELECT 2, 400, 'Once and Future King'
    UNION ALL SELECT 7, 88, 'Microsoft SQL Server 2008'
    UNION ALL SELECT 8, 100, 'Bonfire of the Vanities'
    UNION ALL SELECT 9, 100, 'Canary Row'
    UNION ALL SELECT 10, 400, '1916'
    UNION ALL SELECT 11, 100, 'The Picture of Dorian Gray'
    UNION ALL SELECT 12, 88, 'The Disasters of War'
)
, BOOK_TO_SELLER_MAP AS
(
    SELECT
        B.*
    ,   DENSE_RANK() OVER (PARTITION BY B.seller_id ORDER BY B.internal_book_id ASC) AS unique_book_id_for_seller
    FROM
        BOOKS B
)
SELECT
    *
FROM 
    BOOK_TO_SELLER_MAP V
ORDER BY
    V.seller_id
,   V.unique_book_id_for_seller

Результаты

internal_book_id seller_id title                      unique_book_id_for_seller
7                88        Microsoft SQL Server 2008  1
12               88        The Disasters of War       2
-------------------------------------------------------------------------------
1                100       Secret of NIMH             1
8                100       Bonfire of the Vanities    2
9                100       Canary Row                 3
11               100       The Picture of Dorian Gray 4
-------------------------------------------------------------------------------
2                400       Once and Future King       1
10               400       1916                       2
0 голосов
/ 13 августа 2012

OMG Пони правильно, что последовательности являются единственным правильным способом достижения этого. На самом деле другого жизнеспособного варианта не существует.

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