Хранимая процедура SQL Server для выгрузки старых X-записей при добавлении новых - PullRequest
1 голос
/ 24 февраля 2011

У меня есть сценарий лицензирования, при котором, когда человек активирует новую систему, он добавляет старые активации в таблицу блокировки, чтобы они могли активировать только свои последние X системы. Мне нужно передать параметр того, сколько последних активаций сохранить, и все старые активации должны быть добавлены в таблицу блокировки, если они еще не заблокированы. Я не уверен, как лучше это сделать, то есть временная таблица (чего я никогда не делал) и т. Д.

Например, активация поступает от Джона Доу в System XYZ. Затем мне нужно будет запросить таблицу активаций для всех активаций Джона Доу и отсортировать их по DATE DESC. В этом случае у Джона Доу может быть лицензия на две системы, поэтому мне нужно, чтобы все записи старше, чем первые 2, были деактивированы, т.е. вставлены в таблицу блокировок.

Заранее благодарим за помощь.

Ответы [ 3 ]

1 голос
/ 24 февраля 2011

Что-то вроде этого возможно?

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 голосов
/ 24 февраля 2011

Прежде чем тратить время на чтение и пробовать мой подход, я хочу сказать, что ответ Джо Стефанелли - превосходный - короткий, компактный, продвинутый и, вероятно, лучше моего, особенно с точки зрения производительности.С другой стороны, производительность не может быть вашей первой проблемой (сколько активаций вы ожидаете в день? В час? В минуту?), И мой пример может быть легче читать и понимать.

Как я не понимаюЯ не знаю, как настроена схема вашей базы данных, я сделал несколько предположений.Вы, вероятно, не сможете использовать этот код в качестве шаблона для копирования и вставки, но он должен дать вам представление о том, как это сделать.

Вы говорили о таблице блокировки, поэтому я считаю, что у вас естьпричина дублировать порции данных во вторую таблицу.Если возможно, я бы предпочел использовать флаг блокировки в таблице, содержащей системные данные, но, очевидно, это зависит от вашего сценария.

Обратите внимание, что в настоящее время у меня нет доступа к 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
0 голосов
/ 24 февраля 2011

Вероятно, было бы проще связать 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...