Как создать уникальный ключ пользователя - PullRequest
2 голосов
/ 13 мая 2010

Сценарий: у меня есть довольно общая таблица (Данные), в которой есть столбец идентификаторов. Данные в этой таблице сгруппированы (скажем, по городам).

Пользователям нужен идентификатор для печати на бумажных бланках и т. Д. Пользователи могут получить доступ только к данным своих сайтов, поэтому, если они используют столбец идентификаторов для этой цели, они увидят нечетные числа (например, пользователь «Нью-Йорк» может увидеть 1,37,2028 ... в качестве перечисленных ключей.

В идеале они увидят 1,2,3 ... (или что-то подобное)

Проблема, конечно же, заключается в параллелизме. Это веб-приложение, которое вы не можете просто получить: UserId = Выбрать количество (*) + 1 из данных, где город = 'Нью-Йорк'

Кто-нибудь придумал какие-нибудь хитрые пути решения этой проблемы?

Обновлено - из комментариев ниже я думаю, что хочу что-то вроде SP ниже. Не совсем уверен, как рекурсия должна работать в блоке CATCH.

ALTER PROCEDURE [dbo].[DataContainer_Insert] 
@SomeData varchar(max),
@DataContainerId int out    
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    BEGIN TRY
        SELECT @UserId = MAX(UserId) From DataContainer
        INSERT INTO DataContainer (UserId, SomeData)
        VALUES (@UserId, SomeData)

        SELECT @DataContainerId = scope_identity()
    END TRY
    BEGIN CATCH
        --try again
        exec DataContainer_Insert @DataContainerId, @SomeData
    END CATCH       

END

Ответы [ 3 ]

1 голос
/ 13 мая 2010

Что ж, вы можете использовать свою идею UserId = Select Count(*)+1 from Data Where City='New York', если добавите ограничение уникальности для всего города и UserId (чтобы гарантировать, что когда-либо будет только 1 экземпляр определенного Id и City). Тогда вам просто нужно уметь обрабатывать нарушения ограничений (путем повторной отправки).

1 голос
/ 13 мая 2010

Как общее замечание: Вы можете сделать что-то вроде

newUserId = Select MAX(UserId)+1 from Data Where City='New York'
INSERT INTO data (...) VALUES (newUserId, ...)

даже в сценарии одновременного доступа (например, веб-приложения), если вы используете надлежащий контроль параллелизма, т. Е. (A) блокировка или (b) транзакции с соответствующим уровень изоляции.

См. вопрос 1994771 для углубленного анализа того, как вы можете сделать что-то подобное с SQL Server.

1 голос
/ 13 мая 2010

В некоторых ситуациях, если я отправляю обратно с сервера данные, полученные с использованием GROUP BY в операторе SELEC T, и мне нужно что-то вроде id каждой строки, я использую ROW_NUMBER () (см. http://msdn.microsoft.com/en-us/library/ms186734.aspx). Это также хорошо в случае подкачки данных (см. Простой пример в http://weblogs.asp.net/Firoz/archive/2005/06/12/411949.aspx). Из-за этого требовался SQL Server 2005 или выше. Вы не написали, какой SQL Server вы использовали.

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