Как добавить столбец "последний измененный" и "созданный" в таблице 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
являются столбцами даты и времени.
У вас есть следующие варианты:
Решение без триггеров - я где-то читал, что "Лучший способ написать триггеры - это не писать такие". и вы должны знать, что в целом они наносят ущерб производительности. Так что, если вы можете избежать их, лучше сделать это, даже используя триггеры, в некоторых случаях это может показаться проще всего.
Поэтому просто отредактируйте все свои операторы INSERT
и UPDATE
, чтобы включить текущую UserID
и текущую дату и время. Если такой user ID
не может быть определен (анонимный пользователь), вы можете использовать вместо него 0
и значение столбцов по умолчанию (если не указан user ID
, будет NULL
). Когда вы увидите, что значения NULL
вставлены, вы должны найти "виновные" заявления и отредактировать их.
Решение с помощью триггеров - вы можете создать триггер 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