Как мне следует реализовать поле «autonumber» в SQL Server 2005? - PullRequest
3 голосов
/ 24 марта 2009

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

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

Пример структуры таблицы:

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 для любого клиента и использовать это значение для INSERT, но это может привести к проблемам параллелизма. Я рассматривал возможность использования транзакции, но я не совсем уверен, какой самый широкий диапазон изоляции может быть использован для этого. Я буду использовать LINQ to SQL, но я чувствую, что это не имеет отношения.

Ответы [ 4 ]

2 голосов
/ 24 марта 2009

Кто-то исправит меня, если я ошибаюсь, но , пока ваш вызов 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

1 голос
/ 24 марта 2009

Это странный способ хранения данных, но, если он вам нужен, в нем нет ничего встроенного.

Ваше предложение о Max (ClientOrderID) является простым и довольно простым для реализации (следуйте советам Джона Макинтайра). Вероятно, он будет хорошо работать на столах с несколькими тысячами заказов. По мере роста таблицы этот подход, конечно, будет замедляться.

Предложение Ника ДеВора о таблице поиска немного сложнее в реализации, но существенно не повлияет на рост данных.

В зависимости от того, где / когда вам на самом деле нужен ClientOrderID, вы можете вычислить идентификатор при необходимости, как показано ниже:

SELECT *,
ROW_NUMBER() OVER(ORDER BY OrderID) AS ClientOrderID
FROM Orders
WHERE ClientID = 1

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

1 голос
/ 24 марта 2009

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

1 голос
/ 24 марта 2009

Вы можете использовать шаблон Repository для обработки ваших заказов и позволить ему контролировать количество заказов каждого конкретного клиента. Если вы правильно внедрили OrderRepository, он мог бы контролировать параллелизм и нумерацию ордера перед сохранением его в базе данных (пусть репозиторий, а не db устанавливает номер).

Шаблон репозитория: http://martinfowler.com/eaaCatalog/repository.html

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