#sql #sql-server #schema
#sql #sql-сервер #схема
Вопрос:
У меня есть требование к базе данных, которое немного отличается от стандартной системы выставления счетов, которую вы видите в большинстве введений в БД. В моей системе выставления счетов есть несколько «офисов», которые не связаны между собой. Следовательно, соответствующие номера счетов различны для каждого офиса. Фактический номер счета-фактуры явно отличается от первичного ключа.
Например, офисы A и B могут иметь разные счета-фактуры # 1005.
Существует ли наилучшая практика хранения счетчика для другой таблицы?
create table Offices (
Id integer primary key,
InvoiceCounter integer not null,
Name varchar(32) not null
);
create table Invoices (
Id int primary key,
InvoiceNumber int not null,
Comment varchar(512) not null
-- other columns...
);
Это алгоритм, о котором я подумал при создании нового счета:
- Получите текущий счетчик счетов для Office.
- Увеличьте на единицу и вставьте вместе со счетом.
- Обновите Office новым номером счета-фактуры.
Имеет ли это смысл?
Комментарии:
1. Является ли обязательным повторное использование # 1005 в нескольких офисах? Почему бы просто не поставить Office. Идентификатор в таблице счетов-фактур и полагаться на столбец идентификаторов в таблице счетов-фактур?
2. @NathanSkerl — Я должен был упомянуть, что существует также импорт из существующей базы данных из каждого офиса. Счета-фактуры, очевидно, печатаются, и поэтому ссылка на 1005 в A должна быть нетронутой, если клиент звонит по поводу своего распечатанного счета-фактуры с # 1005.
Ответ №1:
Одна вещь, о которой вам нужно позаботиться, — это вероятность возникновения условий гонки, поскольку. Например. люди пытаются получить следующий Inv #, и они оба получают 1006 обратно.
Чтобы избежать этого, используйте sp_getapplock для блокировки во время вычисления следующего числа
Причина, по которой это хорошая идея, заключается в том, что транзакции обычно не блокируют чтение. например, T1 считывает 1005, но перед тем, как записать 1006, T2 также считывает 1005. Когда T1 завершает транзакцию, T2 продолжает и также записывает 1006. Это приведет к сбою вашей транзакции, если ваш уникальный ключ верен.
Ответ №2:
Я думаю, вы хотите попытаться явно не блокировать, если сможете. Делайте это только в крайнем случае. Разве вы не можете просто повторить транзакцию, если транзакция завершается неудачно из-за того, что две транзакции для одного и того же офиса запрашивают один и тот же номер счета? Неудачная транзакция просто должна повторить попытку получения следующего доступного номера счета для данного офиса.
Предполагается, что у вас есть уникальный ключ, который содержит номер офиса и номер счета.