Как мне следует реализовать поле “autonumber” в SQL Server 2005?
Вопрос
Я знаю о полях ИДЕНТИФИКАЦИИ, но у меня такое чувство, что я не смог бы использовать их для решения своей проблемы.
Допустим, у меня есть несколько клиентов.У каждого клиента есть несколько заказов.Каждый клиент должен иметь последовательную нумерацию своих заказов, специфичную для него.
Пример структуры таблицы:
Orders:
OrderID | ClientID | ClientOrderID | etc...
Некоторыми примерами строк для этой таблицы могут быть:
OrderID | ClientID | ClientOrderID | etc...
1 | 1 | 1 | ...
2 | 1 | 2 | ...
3 | 2 | 1 | ...
4 | 3 | 1 | ...
5 | 1 | 3 | ...
6 | 2 | 2 | ...
Я знаю, что наивным способом было бы взять MAX ClientOrderID для любого клиента и использовать это значение для вставок, но это было бы связано с проблемами параллелизма.Я рассматривал возможность использования транзакции, но я не совсем уверен, какая самая широкая область изоляции может быть использована для этого.Я буду использовать LINQ для SQL, но у меня такое чувство, что это не имеет отношения к делу.
Решение
Кто-нибудь, поправьте меня, если я ошибаюсь, но пока ваш вызов MAX() выполняется на том же шаге, что и ваша вставка, у вас не будет проблем с параллелизмом.
Таким образом, вы могли бы не делай
select @newOrderID=max(ClientOrderID) + 1
from orders
where clientid=@myClientID;
insert into ( ClientID, ClientOrderID, ...)
values( @myClientID, @newOrderID, ...);
Но ты может делай
insert into ( ClientID, ClientOrderID, ...)
select @myClientID, max(ClientOrderID) + 1, ...
from orders
where clientid=@myClientID;
Я предполагаю, что OrderID - это столбец идентификатора.
Опять же, если я ошибаюсь в этом, пожалуйста, дайте мне знать.Предпочтительно с URL-адресом
Другие советы
Вы могли бы использовать шаблон репозитория для обработки ваших заказов и позволить ему контролировать количество заказов каждого конкретного клиента.Если вы правильно реализуете OrderRepository, он может контролировать параллелизм и нумеровать заказ перед сохранением его в базе данных (пусть репозиторий, а не база данных, устанавливает номер).
Шаблон репозитория: http://martinfowler.com/eaaCatalog/repository.html
Одна из возможностей (хотя мне не нравится этого делать) - создать таблицу подстановки, которая сообщала бы вам наибольший номер заказа, указанный для каждого поставщика.Внутри транзакции вы бы извлекли самую последнюю из VendorOrderNumber, сохранили свой новый заказ, увеличили значение в VendorOrderNumber, зафиксировали транзакцию.
Это странный способ хранения данных, но если предположить, что вам это нужно, то нет ничего встроенного, что вы могли бы использовать.
Ваше предложение Max (ClientOrderID) прямолинейно и довольно легко реализовать (следуйте совету Джона Макинтайра).Вероятно, это будет приемлемо хорошо работать на столах с несколькими тысячами заказов.По мере роста таблицы этот подход, конечно, замедлится.
Предложение Ника Девора о таблице подстановки немного сложнее реализовать, но рост объема данных существенно не повлияет на него.
В зависимости от того, где / когда вам действительно нужен ClientOrderID, вы можете вычислить идентификатор, когда это необходимо, следующим образом:
SELECT *,
ROW_NUMBER() OVER(ORDER BY OrderID) AS ClientOrderID
FROM Orders
WHERE ClientID = 1
Это предполагает, что идентификаторы CLIENTORDERID находятся в той же последовательности, что и OrderID .Фактически не сохраняя идентификатор, его неудобно использовать в качестве ключа к чему-либо еще.Рост объема данных не должен повлиять на этот подход.