У меня есть бизнес-требование, чтобы каждая запись в таблице счетов имела идентификатор, который выглядит как ГГГГНННННН.
Часть NNNNNN должна перезапускаться в начале каждого года. Итак, первая строка, введенная в 2016 году, будет выглядеть как 2016000001, а вторая как 2016000002 и т. Д. Допустим, последняя запись за 2016 год была 2016123456, Следующая строка (из 2017) должна выглядеть как 2017000001
Мне не нужен этот идентификатор, чтобы быть первичным ключом, и я также храню дату создания. Идея состоит в том, что этот «идентификатор отображения» является уникальным (поэтому я могу сделать запрос по нему) и способен работать с группой людей по годам.
Вряд ли какие-либо записи будут удалены; однако я был бы склонен защищаться от чего-то подобного.
Есть ли способ, которым я мог бы создать этот идентификатор без необходимости запрашивать максимальный идентификатор в этом году каждый раз, когда вставлять новую строку?
Идеи:
- А
CreateNewInvoiceSP
, который получаетMAX
значение за этот год (хрен) - Какая-то волшебная встроенная функция для именно этого (я могу мечтать правильно)
- Возможность указать какой-либо UDF или что-то в объявлении
IDENTITY
илиDEFAULT
(??) - Представление, которое использует
PARTITION OVER + ROW()
(удалено будет проблематично) - Триггер включен
INSERT
(все равно нужно выполнить какой-тоMAX
запрос :() - Ежегодная справочная работа, обновляемая таблица с MAX для каждого вставленного года, который я тогда ... Что-то ?!
Все это немного не идеально. Любые идеи или варианты приветствуются!
источник
Ответы:
На вашем поле есть 2 элемента
Их не нужно хранить как одно поле
Пример:
YEAR(GETDATE())
Затем создайте вычисляемый столбец, объединяя их (с соответствующим форматированием). Последовательность может быть сброшена при смене года.
Пример кода в SQLfiddle : * (SQLfiddle не всегда работает)
источник
SEQUENCE
в начале каждого года?NEXT VALUE FOR
вCASE
заявлении (я пытался)Рассматривали ли вы создать поле идентификации с seed = 2016000000?
Это семя должно автоматически автоинкрементироваться каждый год, например, ночью 2017/1/1 вы должны запланировать
Но я уже вижу проблемы с дизайном, например: что если у вас есть миллион записей?
источник
В этом сценарии я умножил год на 10 ^ 6 и добавил к нему значение последовательности. Это имеет то преимущество, что не требует вычисляемого поля с его (небольшими) текущими издержками, и поле можно использовать как
PRIMARY KEY
.Есть две возможные ошибки:
убедитесь, что ваш множитель достаточно велик, чтобы никогда не быть исчерпан, и
вам не гарантируется последовательность без пробелов из-за кэширования последовательности.
Я не эксперт по SQL Server, но вы, вероятно, можете установить событие для запуска в 201x 00:00:00, чтобы сбросить вашу последовательность в ноль. Это также то, что я сделал на Firebird (или это был Interbase?).
источник
Изменить: это решение не работает под нагрузкой
Я не фанат триггеров, но это, кажется, лучшее, что я мог бы решить.
Плюсы:
Изменить: Минусы:
(Благодарю @gbn, поскольку я черпал вдохновение из их ответа) (Любая обратная связь и указание на очевидные ошибки приветствуются :)
Добавить несколько новых
COLUMN
иINDEX
Добавить новый
TRIGGER
источник
NULL
значений. Вернуться к чертежной доске ...ON Previous.Id = (I.Id -1)
должен просто искать), но да, по-прежнему не работает. Если бы я мог заблокировать таблицу (?) Во время вставки и запуска, то я думаю, что это сработало бы. Но это звучит как запах кода.