Где хранить счетчик для столбца другой таблицы?

#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...
);
 

Это алгоритм, о котором я подумал при создании нового счета:

  1. Получите текущий счетчик счетов для Office.
  2. Увеличьте на единицу и вставьте вместе со счетом.
  3. Обновите Office новым номером счета-фактуры.

Имеет ли это смысл?

Комментарии:

1. Является ли обязательным повторное использование # 1005 в нескольких офисах? Почему бы просто не поставить Office. Идентификатор в таблице счетов-фактур и полагаться на столбец идентификаторов в таблице счетов-фактур?

2. @NathanSkerl — Я должен был упомянуть, что существует также импорт из существующей базы данных из каждого офиса. Счета-фактуры, очевидно, печатаются, и поэтому ссылка на 1005 в A должна быть нетронутой, если клиент звонит по поводу своего распечатанного счета-фактуры с # 1005.

Ответ №1:

Одна вещь, о которой вам нужно позаботиться, — это вероятность возникновения условий гонки, поскольку. Например. люди пытаются получить следующий Inv #, и они оба получают 1006 обратно.

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

Причина, по которой это хорошая идея, заключается в том, что транзакции обычно не блокируют чтение. например, T1 считывает 1005, но перед тем, как записать 1006, T2 также считывает 1005. Когда T1 завершает транзакцию, T2 продолжает и также записывает 1006. Это приведет к сбою вашей транзакции, если ваш уникальный ключ верен.

Ответ №2:

Я думаю, вы хотите попытаться явно не блокировать, если сможете. Делайте это только в крайнем случае. Разве вы не можете просто повторить транзакцию, если транзакция завершается неудачно из-за того, что две транзакции для одного и того же офиса запрашивают один и тот же номер счета? Неудачная транзакция просто должна повторить попытку получения следующего доступного номера счета для данного офиса.

Предполагается, что у вас есть уникальный ключ, который содержит номер офиса и номер счета.