Создание столбца «Дата обновления» в MS SQL? - PullRequest
4 голосов
/ 27 августа 2010

Есть ли какой-нибудь простой способ создать столбец в MS SQL, который будет отслеживать последний раз, когда обновлялась запись?

Я хотел бы иметь два поля.Один, чтобы отслеживать, когда была создана запись.Это просто.Создайте поле даты и времени и установите его по умолчанию на getdate ().Однако второе поле швов будет немного сложнее.Я хочу, чтобы в нем была указана самая последняя дата (и время) записи.

Мои параметры:

  • Включить getdate () в каждом операторе обновления - не вариант, этиДоступ к таблицам будет осуществляться из MS Access
  • Разрешать обновления только через SP.- не вариант, эти таблицы будут доступны из MS Access
  • Создание триггеров для каждой таблицы - БД воссоздана на многих машинах, и я боюсь, что она будет конфликтовать или будет забыта или не синхронизирована.

Есть ли другие варианты?

Ответы [ 3 ]

5 голосов
/ 27 августа 2010

Триггеры в значительной степени ваш единственный вариант здесь. Что мешает кому-либо обновлять таблицы с помощью SSMS, эти обновления не будут обновлять столбец даты обновления в этом случае

1 голос
/ 28 августа 2010

Вариант 4:

Создайте хранимую процедуру, которая автоматически создает триггеры для всех таблиц в вашей базе данных.В SQL 2005 опционально запускайте этот триггер каждый раз, когда создается любая таблица (с использованием триггера DDL).

CREATE PROC UpdateTriggersCreate
AS
DECLARE
   @TableSchema sysname,
   @TableName sysname,
   @PrimaryKeys nvarchar(4000),
   @ObjectName nvarchar(4000)
   @TriggerName nvarchar(4000),
   @SQL nvarchar(4000);
SET @TableName = '';
SET @TableSchema = '';
WHILE 1 = 1 BEGIN
   SELECT TOP 1
      @TableSchema = TABLE_SCHEMA,
      @TableName = TABLE_NAME
   FROM INFORMATION_SCHEMA.COLUMNS
   WHERE
      COLUMN_NAME = 'LastUpdatedDate'
      AND (
         TABLE_SCHEMA > @TableSchema
         OR (
            TABLE_SCHEMA = @TableSchema
            AND TABLE_NAME > @TableName
         )
      )
   ORDER BY TABLE_SCHEMA, TABLE_NAME;
   IF @@RowCount = 0 BREAK;

   IF NOT EXISTS (
      SELECT *
      FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
      WHERE
         C.CONSTRAINT_TYPE = 'PRIMARY KEY'
         AND C.TABLE_SCHEMA = @TableSchema
         AND C.TABLE_NAME = @TableName
   ) BEGIN
       PRINT '-- Not processing table ''' + @TableSchema + '.' + @TableName + ''' because automatic last updated triggers cannot be used on tables with no primary key.';
       CONTINUE;
   END;

   SET @PrimaryKeys = NULL;
   SELECT @PrimaryKeys = Coalesce(@PrimaryKeys + ' AND T.', 'T.') + QuoteName(Y.COLUMN_NAME) + ' = I.' + QuoteName(Y.COLUMN_NAME)
   FROM
      INFORMATION_SCHEMA.TABLE_CONSTRAINTS T
      INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE Y
         ON T.CONSTRAINT_CATALOG = Y.CONSTRAINT_CATALOG
         AND T.CONSTRAINT_SCHEMA = Y.CONSTRAINT_SCHEMA
         AND T.CONSTRAINT_NAME = Y.CONSTRAINT_NAME
   WHERE
      T.CONSTRAINT_TYPE = 'PRIMARY KEY'
      AND T.TABLE_SCHEMA = @TableSchema
      AND T.TABLE_NAME = @TableName;
   -- order is not important which is good because ORDER BY is unreliable in this case

   SET @ObjectName = @TableSchema + '.' + @TableName;
   SET @TriggerName = 'TR_' + Replace(@ObjectName, '.', '_') + '_U_TimeUpdated';
   SET @SQL = 'IF Object_ID(''' + @TriggerName + ''', ''TR'') IS NOT NULL DROP TRIGGER ' + @TriggerName;
   EXEC sp_executesql @SQL;
   SET @SQL = 'CREATE TRIGGER ' + @TriggerName + ' ON ' + @ObjectName + ' FOR INSERT
AS
SET NOCOUNT ON
UPDATE T
SET T.LastUpdatedDate = GetDate()
FROM
   ' + @ObjectName + ' T
   INNER JOIN Inserted I ON ' + @PrimaryKeys;

   EXEC sp_executesql @SQL;
END;

После того, как у вас есть такая хранимая процедура, запланируйте ее запуск один раз в день или (в sql2005 и выше) в ответ на создание таблиц DDL.

Обновление 1

Код теперь правильно обрабатывает схему и ищет первичные ключи.Он также сообщает и пропускает таблицы, которые не имеют первичного ключа.

Я не уверен, что я обработал все синтаксические ошибки - я адаптировал его из кода, в котором я делал это раньше и не сделална самом деле проверить это.Я уверен, что вы можете понять это.

0 голосов
/ 27 августа 2010

Сохраненные процессы - это вариант с Access, но вы должны перехватить событие в VBA и вместо этого вызвать сохраненный процесс, а затем Me.Undo.

Я сделал это, но много месяцев назад и неИзвините, у вас нет примера кода.

В противном случае триггеры являются обычным способом, до или после них.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...