Прежде чем тратить время на чтение и пробовать мой подход, я хочу сказать, что ответ Джо Стефанелли - превосходный - короткий, компактный, продвинутый и, вероятно, лучше моего, особенно с точки зрения производительности.С другой стороны, производительность не может быть вашей первой проблемой (сколько активаций вы ожидаете в день? В час? В минуту?), И мой пример может быть легче читать и понимать.
Как я не понимаюЯ не знаю, как настроена схема вашей базы данных, я сделал несколько предположений.Вы, вероятно, не сможете использовать этот код в качестве шаблона для копирования и вставки, но он должен дать вам представление о том, как это сделать.
Вы говорили о таблице блокировки, поэтому я считаю, что у вас естьпричина дублировать порции данных во вторую таблицу.Если возможно, я бы предпочел использовать флаг блокировки в таблице, содержащей системные данные, но, очевидно, это зависит от вашего сценария.
Обратите внимание, что в настоящее время у меня нет доступа к SQL Server, поэтому я мог быне проверять действительность кода.Я старался изо всех сил, но в нем могут быть опечатки, хотя.
Первое предположение: минималистическая таблица "зарегистрированных систем":
CREATE TABLE registered_systems
(id INT NOT NULL IDENTITY,
owner_id INT NOT NULL,
system_id VARCHAR(MAX) NOT NULL,
activation_date DATETIME NOT NULL)
Второе предположение: минималистичные "заблокированные системы"table:
CREATE TABLE locked_out_systems
(id INT NOT NULL,
lockout_date DATETIME NOT NULL)
Затем мы можем определить хранимую процедуру для активации новой системы.Он принимает в качестве параметров owner_id, количество разрешенных систем и, конечно, новый идентификатор системы.
CREATE PROCEDURE register_new_system
@owner_id INT,
@allowed_systems_count INT,
@new_system_id VARCHAR(MAX)
AS
BEGIN TRANSACTION
-- Variable declaration
DECLARE @sid INT -- Storage for a system id
-- Insert the new system
INSERT INTO registered_systems
(owner_id, system_id, activation_date)
VALUES
(@owner_id, @system_od, GETDATE())
-- Use a cursor to query all registered-and-not-locked-out systems for this
-- owner. Skip the first @allowed_systems_count systems, then insert the
-- remaining ones into the lockout table.
DECLARE c_systems CURSOR FAST_FORWARD FOR
SELECT system_id FROM
registered_systems r
LEFT OUTER JOIN
locked_out_systems l
ON r.system_id = l.system_id
WHERE l.system_id IS NULL
ORDER BY r.activation_date DESC
OPEN c_systems
FETCH NEXT FROM c_systems INTO @sid
WHILE @@FETCH_STATUS = 0
BEGIN
IF @allowed_systems_count > 0
-- System still allowed, just decrement the counter
SET @allowed_systems_count = @allowed_systems_count -1
ELSE
-- All allowed systems used up, insert this one into lockout table
INSERT INTO locked_out_systems
(id, lockout_date)
VALUES
(@sid, GETDATE())
FETCH NEXT FROM c_systems INTO @sid
END
CLOSE c_systems
DEALLOCATE c_systems
COMMIT