SQL Server: триггер, как прочитать значение для вставки, обновления, удаления - PullRequest
17 голосов
/ 14 декабря 2011

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

ALTER TRIGGER [dbo].[UpdateUserCreditsLeft] 
   ON  [dbo].[Order]
   AFTER INSERT,UPDATE,DELETE
AS 
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE 
    @UserId INT,

    SELECT @UserId = INSERTED.UserId FROM INSERTED, DELETED

    UPDATE dbo.[User] SET CreditsLeft = CreditsLeft - 1 WHERE Id = @UserId
END

Ответы [ 3 ]

29 голосов
/ 14 декабря 2011

Обратите внимание, что inserted, deleted означает то же самое, что и inserted CROSS JOIN deleted, и дает каждую комбинацию каждой строки. Я сомневаюсь, что это то, что вы хотите.

Нечто подобное может помочь вам начать ...

SELECT
  CASE WHEN inserted.primaryKey IS NULL THEN 'This is a delete'
       WHEN  deleted.primaryKey IS NULL THEN 'This is an insert'
                                        ELSE 'This is an update'
  END  as Action,
  *
FROM
  inserted
FULL OUTER JOIN
  deleted
    ON inserted.primaryKey = deleted.primaryKey


В зависимости от того, что вы хотите сделать, вы затем ссылаетесь на интересующую вас таблицу с помощью inserted.userID или deleted.userID и т. Д.


Наконец, имейте в виду, что inserted и deleted являются таблицами и могут (и могут) содержать более одной записи.

Если вы вставите 10 записей одновременно, таблица inserted будет содержать ВСЕ 10 записей. То же самое касается удалений и таблицы deleted. И обе таблицы в случае обновления.


EDIT Пример запуска по редактированию OP.

ALTER TRIGGER [dbo].[UpdateUserCreditsLeft] 
  ON  [dbo].[Order]
  AFTER INSERT,UPDATE,DELETE
AS 
BEGIN

  -- SET NOCOUNT ON added to prevent extra result sets from
  -- interfering with SELECT statements.
  SET NOCOUNT ON;

  UPDATE
    User
  SET
    CreditsLeft = CASE WHEN inserted.UserID IS NULL THEN <new value for a  DELETE>
                       WHEN  deleted.UserID IS NULL THEN <new value for an INSERT>
                                                    ELSE <new value for an UPDATE>
                  END
  FROM
    User
  INNER JOIN
    (
      inserted
    FULL OUTER JOIN
      deleted
        ON inserted.UserID = deleted.UserID  -- This assumes UserID is the PK on UpdateUserCreditsLeft
    )
      ON User.UserID = COALESCE(inserted.UserID, deleted.UserID)

END


Если PrimaryKey UpdateUserCreditsLeft отличается от UserID, используйте его вместо FULL OUTER JOIN.

24 голосов
/ 14 декабря 2011

Нет updated динамической таблицы. Есть только inserted и deleted. По команде UPDATE старые данные сохраняются в динамической таблице deleted, а новые значения сохраняются в динамической таблице inserted.

Думайте о UPDATE как о комбинации DELETE/INSERT.

0 голосов
/ 14 декабря 2011

Вот синтаксис для создания триггера:

CREATE TRIGGER trigger_name
ON { table | view }
[ WITH ENCRYPTION ]
{
    { { FOR | AFTER | INSTEAD OF } { [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] }
        [ WITH APPEND ]
        [ NOT FOR REPLICATION ]
        AS
        [ { IF UPDATE ( column )
            [ { AND | OR } UPDATE ( column ) ]
                [ ...n ]
        | IF ( COLUMNS_UPDATED ( ) { bitwise_operator } updated_bitmask )
                { comparison_operator } column_bitmask [ ...n ]
        } ]
        sql_statement [ ...n ]
    }
} 

Если вы хотите использовать при обновлении, вы можете сделать это только с разделом IF UPDATE ( column ). Это невозможно сделать то, что вы просите.

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