Используйте триггер SQL Server для обновления столбца в другой таблице после вставки - PullRequest
0 голосов
/ 02 июня 2018

Я пытаюсь выполнить следующее с помощью триггера SQL Server: после вставки новой строки в таблицу мне бы хотелось обновить столбец в другой таблице.

Например: у меня есть таблица с именем Users и таблица с именем Activity.Каждый раз, когда клиент подключается к серверу, строка вставляется в таблицу Activity;после вставки строки (которая содержит user_id) я хотел бы обновить столбец в таблице Users, в которой хранятся дата и время последнего действия.

UPDATE Users
SET Last_Activity_TimeStamp = GETDATE()
WHERE Users.User_ID = Activity.User_ID

Но SSMS выдаетсообщение об ошибке:

Не удалось связать многоэлементный идентификатор "dbo.Activity.User_ID"

Если я изменил приведенный выше оператор обновления на:

UPDATE Users
SET Last_Activity_TimeStamp = GETDATE()
WHERE Users.User_ID = User_ID

Все строки в таблице Users обновлены.

Я понимаю, что существует таблица Inserted и что строки добавляются там до того, как они вставляются в основную таблицу Activity,однако, потенциально у меня подключается много пользователей, и в таблицу Activity будет вставлено много строк.Потенциально 1000 в секунду.Я хотел бы знать, как получить user_id строки, вставляемой в таблицу Activity, и обновить Last_Activity_TimeStamp в таблице Users.

Редактировать: Я думаю, где мне не хватаетя знаю, что я не знаю, сколько строк может быть в таблице Inserted в любое время, учитывая, что в моем проекте одна транзакция вставляет только одну строку.Возможно ли, что в таблице Inserted содержится более одной строки из других активных транзакций, поскольку к ней подключаются и отключаются несколько пользователей?

Любая помощь будет принята с благодарностью!

Спасибовы

Ответы [ 3 ]

0 голосов
/ 02 июня 2018

Нельзя ссылаться на поля таблицы, например dbo.Activity.User_ID .Измените код триггера следующим образом.

CREATE TRIGGER Trk_Test 
    ON [dbo].[Activity]
    FOR INSERT
AS
BEGIN
    DECLARE @Id INT = 0

    SELECT @ID = [User_Id] FROM inserted

    UPDATE Users 
    SET Last_Activity_TimeStamp = GETDATE()
    WHERE [User_Id] = @Id

END

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

0 голосов
/ 02 июня 2018

В других ответах не учитывается, что псевдотаблица Inserted в триггере будет иногда содержать НЕСКОЛЬКО строк - нужно никогда выбирать одно значение - НЕ РАБОТАЕТ , как ожидается, если одновременно вставляется несколько строк.

Триггер должен быть записан на основе набора Чтобы справиться с этой ситуацией - что на самом деле довольно легко - попробуйте что-то вроде этого:

CREATE TRIGGER trgActivityInsert
ON [dbo].[Activity]
FOR INSERT
AS
BEGIN
    UPDATE u
    SET Last_Activity_TimeStamp = GETDATE()
    FROM dbo.Users u
    INNER JOIN Inserted i ON u.User_Id = i.User_Id
END

При этом ваш триггер будет работать отлично, независимо от того, вставляете ли вы одну, десять или сто строк одновременно, и все соответствующиезаписи в таблице dbo.User будут обновлены должным образом.

0 голосов
/ 02 июня 2018

Только одна строка содержит вставленную таблицу для одной транзакции.Для каждого случая, когда данные вставляются в таблицу действий, триггер будет выполняться для каждой отдельной вставки.

Итак, вы можете попробовать это .....

Create Trigger Trigger_UpdateUsers
    ON Activity 
    For INSERT
As
Begin

    Declare @user_id varchar(10)

    SELECT  @user_id = user_id from INSERTED

    UPDATE  Users set Last_Activity_TimeStamp=GETDATE() 
    WHERE   Users.User_ID =@user_id

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