我有一个许可方案,当一个人激活一个新系统时,它会将旧激活添加到一个锁定表中,这样他们只能激活他们最新的X系统。我需要传递一个参数,指出要保留的最近激活次数,并且如果尚未锁定,则应将所有较旧的激活添加到锁定表中。我不确定如何最好地做到这一点,即临时表(我从未做过)等等。
例如,激活来自系统XYZ上的John Doe。然后,我需要查询激活表,查看John Doe的所有激活,并按DATE DESC对其进行排序。在这种情况下,John Doe可能拥有允许两个系统的许可证,因此我需要所有早于前2个停用的记录,即插入锁定表。
提前感谢您的协助。
答案 0 :(得分:1)
或许这样的事情?
insert into lockouts
(<column list>)
select <column list>
from (select <column list>,
row_number() over (order by date desc) as RowNum
from activations) t
where t.RowNum > @NumLicenses
答案 1 :(得分:0)
使用视图或表值函数将row_number()结合起来可能最简单:
WITH ActivationRank AS
(
SELECT SystemId,ProductId,CreatedDate,ROW_NUMBER() OVER(PARTITION BY ProductId ORDER BY CreatedDate DESC) AS RANK
FROM [Activations]
)
SELECT SystemId, ProductId, CASE WHEN RANK < @lockoutParameterOrConstant 0 ELSE 1 END AS LockedOut
FROM ActivationRank
答案 2 :(得分:0)
在你花时间阅读和尝试我的方法之前,我想说Joe Stefanelli的答案是一个很好的答案 - 简短,紧凑,先进,可能比我的更好,特别是在性能方面。另一方面,性能可能不是您首先关注的问题(您每天需要多少次激活?每小时?每分钟?)并且我的示例可能更容易阅读和理解。
由于我不知道您的数据库架构是如何设置的,因此我对它做了一些假设。您可能无法将此代码用作复制和粘贴模板,但它应该让您了解如何执行此操作。
你在谈论一个锁定表,所以我认为你有理由将部分数据复制到第二个表中。如果可能的话,我宁愿在包含系统数据的表中使用锁定标志,但显然这取决于您的方案。
请注意,我目前无法访问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)
第二个假设:简约的“锁定系统”表:
CREATE TABLE locked_out_systems
(id INT NOT NULL,
lockout_date DATETIME NOT NULL)
然后我们可以定义一个存储过程来激活一个新系统。它需要owner_id,允许的系统数量,当然还有新的系统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