Как добавить столбец "последний измененный" и "созданный" в таблице SQL Server?

Я создаю новую схему db для базы данных SQL Server 2012.

Каждая таблица должна иметь два дополнительных столбца с именем modified и created, которые должны автоматически меняться, как только строка будет вставлена ​​или обновлена.

Я не знаю, как лучше всего добраться туда.

Я предполагаю, что триггер - лучший способ справиться с этим.

Я пытался найти примеры с триггерами.. но учебники, которые я нашел, вставляют данные в другую таблицу и т.д.

Я предположил, что это довольно распространенный сценарий, но я еще не смог найти ответ.

Ответы

Ответ 1

Столбец created прост - только столбец DATETIME2(3) с ограничением по умолчанию, которое устанавливается при вставке новой строки:

Created DATETIME2(3) 
   CONSTRAINT DF_YourTable_Created DEFAULT (SYSDATETIME())

Поэтому, когда вы вставляете строку в YourTable и не указываете значение для created, она будет установлена ​​на текущую дату и время.

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

Modified DATETIME2(3)

а затем

CREATE TRIGGER updateModified
ON dbo.YourTable
AFTER UPDATE 
AS
   UPDATE dbo.YourTable
   SET modified = SYSDATETIME()
   FROM Inserted i
   WHERE dbo.YourTable.PrimaryKey = i.PrimaryKey

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

И вам нужно создать триггер AFTER UPDATE для каждой таблицы, в которой вы хотите иметь столбец modified.

Ответ 2

Как правило, вы можете иметь следующие столбцы:

  • LastModifiedBy
  • LastModifiedOn
  • CreatedBy
  • CreatedOn

где LastModifiedBy и CreatedBy являются ссылками на таблицу users (UserID), а столбцы LastModifiedOn и CreatetOn являются столбцами даты и времени.

У вас есть следующие варианты:

  1. Решение без триггеров - я где-то читал, что "Лучший способ написать триггеры - это не писать такие". и вы должны знать, что в целом они наносят ущерб производительности. Так что, если вы можете избежать их, лучше сделать это, даже используя триггеры, в некоторых случаях это может показаться проще всего.

    Поэтому просто отредактируйте все свои операторы INSERT и UPDATE, чтобы включить текущую UserID и текущую дату и время. Если такой user ID не может быть определен (анонимный пользователь), вы можете использовать вместо него 0 и значение столбцов по умолчанию (если не указан user ID, будет NULL). Когда вы увидите, что значения NULL вставлены, вы должны найти "виновные" заявления и отредактировать их.

  2. Решение с помощью триггеров - вы можете создать триггер AFTER INSERT, UPDATE и заполнить там столбцы пользователей. Легко получить текущую дату и время в контексте триггера (используйте, например, GETUTCDATE()). Проблема здесь в том, что триггеры не позволяют передавать/принимать параметры. Таким образом, поскольку вы не вставляете значение user ID и не можете передать его в триггер. Как найти текущего пользователя?

    Вы можете использовать SET CONTEXT_INFO и CONTEXT_INFO. Перед всеми вы insert и update вы должны использовать SET CONTEXT_INFO, чтобы добавить current user ID в текущий контекст, а в триггере вы используете функцию CONTEXT_INFO, чтобы извлечь его.

Таким образом, при использовании триггеров вам снова нужно отредактировать все ваши предложения INSERT и UPDATE - вот почему я предпочитаю их не использовать.

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


С помощью SQL Server 2016 теперь мы можем использовать функцию SESSION_CONTEXT для чтения деталей сеанса. Подробности устанавливаются с помощью sp_set_session_context (как read-only или read and write). Вещи немного удобны для пользователя:

EXEC sp_set_session_context 'user_id', 4;  
SELECT SESSION_CONTEXT(N'user_id');  

Хороший пример.

Ответ 3

Внимание, выше работает нормально, но не во всех случаях, Я потерял много времени и нашел это полезным:

create TRIGGER yourtable_update_insert
ON yourtable
AFTER UPDATE 
as
begin
   set nocount on;
   update yourtable set modified=getdate(), modifiedby = suser_sname()
   from  yourtable t 
   inner join inserted i on t.uniqueid=i.uniqueid 
end
go

set nocount on; необходимо, иначе вы получите ошибку:


Microsoft SQL Server Management Studio


Строка не обновлена.

Данные в строке 5 не были зафиксированы. Источник ошибки: Microsoft.SqlServer.Management.DataTools. Сообщение об ошибке: Обновленные или удаленные значения строк либо не делают строку уникальной, либо изменяют несколько строк (2 строки).

Исправьте ошибки и повторите попытку или нажмите ESC, чтобы отменить изменения.


OK Помощь


Ответ 4

CREATE TRIGGER [dbo].[updateModified]
   ON  [dbo].[Transaction_details] 
   AFTER UPDATE
AS 
BEGIN
    SET NOCOUNT ON;
    UPDATE dbo.Transaction_details
    SET ModifedDate = GETDATE() FROM dbo.Transaction_details t JOIN inserted i ON 
    t.TransactionID = i.TransactionID--SYSDATETIME()
END