У меня есть таблица для запросов, и после того, как они будут одобрены / отклонены, им необходимо назначить собственный последовательный идентификатор, например:
MYCODE-11-0001
MYCODE-11-0002
MYCODE-11-0003
, где MYCODE
не изменяется, но 11
- текущий год, а 0001
- последовательно генерируемый номер, назначенный на год. Так что каждый год он начинается в 0001.
Я никогда не имел дело с триггерами или хранимыми процедурами в SQL Sever, поэтому у меня была идея сделать это в коде через Linq-to-SQL на VB.net, и у меня есть другая таблица в SQL Server, которая отслеживает Next ID
ID NAME NextID
1 Request2011 102
2 Request2012 1
3 Request2013 1
Если они изменили статус на веб-сайте, приложение выбирает имя на основе текущего года, получает NextID
и генерирует RequestID
. LINQ даже перехватит, если NextID
изменилось с момента получения значения, добавления его и попытки сохранить это новое значение.
Уверен, это сработает, но я не совсем доволен, потому что предполагается, что все будет из моего приложения. Я бы чувствовал себя намного лучше, если бы это было сделано на уровне базы данных, и даже лучше, если бы он не опирался на эту таблицу NextID
, которая была у меня.
Есть ли что-нибудь с триггерами и процедурами хранения, которые не были бы слишком сумасшедшими, что позволило бы мне генерировать эти пользовательские идентификаторы? У меня есть смутное представление о том, что я могу запустить триггер при обновлении StatusID
для запуска хранимой процедуры для выполнения некоторых тяжелых работ (генерируется RequestID
, если еще не установлено), но если мне все еще приходится полагаться на NextID
таблица, тогда я должен беспокоиться о блокировке / разблокировке таблицы, а также правильно?
Просто надеюсь, что кто-то посоветуется с людьми, которые знают SQL Server гораздо лучше, чем я.
Примечание: Пользовательский идентификатор назначается только во время утверждения / отклонения запроса, а не когда он был вставлен в базу данных. Каждый запрос имеет свой уникальный автоматически сгенерированный идентификатор PK.
ОБНОВЛЕНИЕ: Возможно, мне придется придерживаться решения кода, так как оно делает все возможное для меня, когда дело касается параллелизма, но я написал триггер только для того, чтобы я мог учиться.
/* --------------------
SETUP
--------------------*/
CREATE TABLE [dbo].[TestData](
[ID] [int] IDENTITY(1,1) NOT NULL,
[data] [varchar](100) NULL,
[RequestID] [varchar](25) NULL,
[StatusID] [int] NULL
)
INSERT INTO TestData
([data],[StatusID])
VALUES
('test',1)
GO
CREATE TABLE [dbo].[NextID](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](75) NULL,
[NextID] [int] NULL,
[DateModified] [date] NULL,
[ModifiedBy] [varchar](75) NULL
)
INSERT INTO NextID
([Name],[NextID])
VALUES('RequestID2011',1)
GO
/* --------------------
TRIGGER
--------------------*/
IF EXISTS (SELECT name FROM sys.objects
WHERE name = 'UpdateStatusID' AND type = 'TR')
DROP TRIGGER dbo.UpdateStatusID;
GO
CREATE TRIGGER UpdateStatusID
ON dbo.TestData
AFTER UPDATE
AS
IF ( UPDATE (StatusID))
BEGIN
DECLARE @nextId int
DECLARE @nextIdName varchar(50)
/* -- Get NextID based on year's count IE: RequestID2011 */
SET @nextIdName = 'RequestID' + CONVERT(VARCHAR, YEAR(GetDate()), 50)
SET @nextid = (Select NextID from dbo.NextID where Name = @nextIdName)
/* -- Increment NextID */
UPDATE dbo.NextID set NextID = @nextid + 1 WHERE Name=@nextIdName
/* -- Set New RequestID */
UPDATE dbo.TestData
SET RequestID = 'MYCODE-' + RIGHT(@nextIdName,2) + '-' + CONVERT(VARCHAR, REPLICATE('0', (4- LEN(@nextid))) + @nextid, 50)
FROM inserted i INNER JOIN dbo.TestData t
ON i.id = t.id
END;
GO
/* --------------------
TEST
--------------------*/
UPDATE dbo.TestData
SET StatusID = 3
WHERE ID = 1;
GO
Чего это не делает, так это защиты от того, что кто-то изменил StatusID
более одного раза (они могут сделать это, но мне нужно только сгенерировать ID один раз) или защиты от людей, одновременно захвативших NextID
и имеющих проблема состояния гонки.
Это также все еще требует от меня иметь несколько записей «RequestIDXXXX» в базе данных на будущие годы.
Предупреждение: Это не обрабатывает параллелизм и это просто работа на моем пути к пониманию триггеров и SQL Server.