SQL Server : trigger how to read value for Insert, Update, Delete

瘦欲@ 提交于 2020-01-11 20:53:48

问题


I have the trigger in one table and would like to read UserId value when a row is inserted, updated or deleted. How to do that? The code below does not work, I get error on 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

回答1:


Please note that inserted, deleted means the same thing as inserted CROSS JOIN deleted and gives every combination of every row. I doubt this is what you want.

Something like this may help get you started...

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


Depending on what you want to do, you then reference the table you are interested in with inserted.userID or deleted.userID, etc.


Finally, be aware that inserted and deleted are tables and can (and do) contain more than one record.

If you insert 10 records at once, the inserted table will contain ALL 10 records. The same applies to deletes and the deleted table. And both tables in the case of an update.


EDIT Examplee Trigger after OPs edit.

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


If the PrimaryKey of UpdateUserCreditsLeft is something other than UserID, use that in the FULL OUTER JOIN instead.




回答2:


There is no updated dynamic table. There is just inserted and deleted. On an UPDATE command, the old data is stored in the deleted dynamic table, and the new values are stored in the inserted dynamic table.

Think of an UPDATE as a DELETE/INSERT combination.




回答3:


Here is the syntax to create a trigger:

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 you want to use On Update you only can do it with the IF UPDATE ( column ) section. That's not possible to do what you are asking.



来源:https://stackoverflow.com/questions/8505924/sql-server-trigger-how-to-read-value-for-insert-update-delete

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!