2011-02-23 84 views
1

我有一个授权方案,当一个人激活一个新系统时,它会将旧激活添加到锁定表中,以便他们只能激活最新的X系统。如果它们尚未锁定,我需要传递一个参数,以保留最近的激活次数以及所有较旧的激活次数应该添加到锁定表中。我不知道如何最好地做到这一点,即临时表(我从来没有做过)等。SQL Server存储过程添加新记录时转储最早的X记录

例如,系统XYZ上的John Doe激活。然后,我需要查询John Doe所有激活表的激活表并按DATE DESC对其进行排序。在这种情况下,John Doe可能有一个允许两个系统的许可证,所以我需要所有比最前面的2个记录还旧的记录,即插入到锁定表中。

在此先感谢您的帮助。

回答

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 
+0

我遇到了一个障碍,也许你可以帮助我。我的激活表具有以下列:CustomerName,KeyCode,MachineName,ActivationDate。 您可以重新激活同一台机器,这样我可能会有10条记录与ActivationDate相同。我需要一些方法来首先获得一个结果集,其中包含DISTINCT和有序的DESC激活,所以我没有重复信息计数的行号在同一台计算机上重新激活。在得到不同的结果集后,我需要按照您的建议应用行号。任何想法如何做到这一点?谢谢。 – Neal 2011-02-24 21:43:02

+0

@Neal:我发布了[我的答案](http://stackoverflow.com/questions/5111048/tsql-to-get-distinct-records-ordered-and-then-apply-row-numbers/5111226#5111226 )在你打开的[后续问题](http://stackoverflow.com/questions/5111048/tsql-to-get-distinct-records-ordered-and-then-apply-row-numbers)上。 – 2011-02-24 22:35:15

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 
0

之前你投资的时间来阅读,并尝试我的方法,我想说乔·斯特法尼利的答案是一个很好的答案 - 简短,紧凑,先进,可能比我的更好,特别是在性能方面。另一方面,表现可能不是您首先关心的问题(您每天预计会有多少次激活?每小时?每分钟?),我的示例可能更易于阅读和理解。

因为我不知道你的数据库模式是如何设置的,所以我做了一些假设。您可能无法将此代码用作复制和粘贴模板,但它应该为您提供有关如何执行此操作的想法。

你说的是锁定表,所以我认为你有理由将数据的部分复制到第二个表中。如果可能的话,我宁愿在包含系统数据的表中使用锁定标志,但显然这取决于您的方案。

请注意,我目前无权访问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 
+0

感谢帕特里克 - 伟大的信息,我感谢你的努力来协助。我没有选择乔的答案,因为这是最简单的实现。 – Neal 2011-02-24 16:20:31