2011-02-23 74 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