当前位置: 首页 > 面试题库 >

创建用于插入,修改和删除的数据库触发器的正确​​语法是什么

许振海
2023-03-14
问题内容

我在SQL Server中有一个数据库触发器的基本情况,但遇到了问题。

我有表 Users (标识,名称,电话等),并且我有表 UsersHistory (标识,user_id操作,字段,时间戳)

我想要一个数据库触发器,随时可以将其插入,更新或删除到用户中,我希望在UsersHistory中创建一个具有用户ID和已完成操作的新记录(插入新的,更新的字段,已删除的ID。基本上是审计日志表。

这是我走了多远,但我不知道如何:

  1. 获取有关修改和删除的ID,以及
  2. 如何获取已更改字段和已执行操作(插入,删除,更新)的列表
CREATE TRIGGER Update_Users_History 
   ON  Users
   AFTER INSERT,DELETE,UPDATE
 AS 
 BEGIN
-- Insert statements for trigger here

insert into UsersHistory (user_id, [action], [fields], timestamp)
select  max(id) as user_id, {action ??},{fields??}  getdate() from Users)

END
GO

有什么建议?


问题答案:

最简单的方法可能只是简单地创建三个触发器-每个操作一个:

CREATE TRIGGER trgUserInsert
ON dbo.User AFTER INSERT
AS BEGIN
   INSERT INTO dbo.UserHistory............
END

CREATE TRIGGER trgUserDelete
ON dbo.User AFTER DELETE
AS BEGIN
   INSERT INTO dbo.UserHistory............
END

CREATE TRIGGER trgUserUpdate
ON dbo.User AFTER UPDATE
AS BEGIN
   INSERT INTO dbo.UserHistory............
END

这样,事情就很简单,您可以轻松地了解自己在做什么,如果您需要插入或删除大量项目,它还可以关闭单个操作的触发器。

在触发器内部,您有两个“伪表”-
Inserted(用于INSERT和UPDATE)和Deleted(用于UPDATE和DELETE)。这些伪表包含新插入值(或UPDATE中更新的值)的值,或已删除(对于DELETE)或已更新的值(对于UPDATE操作,在更新之前的旧值)的值。

你需要知道,如果你更新行,如数量庞大的触发将有一次甚至被称为Inserted以及Deleted通常包含多个行。

作为示例,您可以像这样编写“ AFTER INSERT”触发器(只是猜测您的表结构可能是…。):

CREATE TRIGGER trgUserInsert
ON dbo.User AFTER INSERT
AS BEGIN
   INSERT INTO 
      dbo.UserHistory(UserID, Action, DateTimeStamp, AuditMessage)
      SELECT 
         i.UserID, 'INSERT', getdate(), 'User inserted into table'
      FROM
         Inserted i
END

您正在寻找一种方法来找出此触发器引起的“动作”吗?我看不到有任何方法可以做到,这是将三个触发器分开的另一个原因。找出这一点的唯一方法是对InsertedUpdated表中的行进行计数:

  • 如果两个计数都大于零,则为 UPDATE
  • 如果Inserted表中有行,但表Deleted中没有,则为INSERT
  • 如果Inserted表没有行,但是有Deleted,那是一个DELETE

您还正在寻找“已更新的字段列表”-再次,您实际上将没有任何简单的解决方案。您可以只浏览“用户”表中感兴趣的字段,然后检查

IF UPDATE(fieldname) ......

但这有点乏味。

或者,您可以使用该COLUMNS_UPDATED()函数-
但是,该函数不能为您提供很好的列名列表,而是一个VARBINARY,其中每个列基本上都是一位,并且如果打开了该列,则该列也将被更新。不是很容易使用.....

如果您确实要创建一个大型触发器,则可以以此为基础-它检测导致触发器触发的操作,并将条目插入到User_History表中:

CREATE TRIGGER trgUser_Universal
ON dbo.Users
AFTER INSERT, UPDATE, DELETE
AS BEGIN
  DECLARE @InsHasRows BIT = 0
  DECLARE @DelHasRows BIT = 0

  IF EXISTS(SELECT TOP 1 * FROM INSERTED)
    SET @InsHasRows = 1

  IF EXISTS(SELECT TOP 1 * FROM DELETED)
    SET @DelHasRows = 1

  DECLARE @TriggerAction VARCHAR(20)

  IF @InsHasRows = 1 AND @DelHasRows = 1 
     SET @TriggerAction = 'UPDATE'
  ELSE
     IF @InsHasRows = 1
        SET @TriggerAction = 'INSERT'
     ELSE  
        SET @TriggerAction = 'DELETE'

  IF @InsHasRows = 1
    INSERT INTO dbo.UsersHistory(user_id, [action], [fields], timestamp)
      SELECT i.UserId, @TriggerAction, null, getdate()
      FROM INSERTED i
  ELSE  
    INSERT INTO dbo.UsersHistory(user_id, [action], [fields], timestamp)
      SELECT d.UserId, @TriggerAction, null, getdate()
      FROM DELETED d
END

我还没有弄清楚哪些字段已经更新过了-留给读者练习:-)

这些帮助有用?



 类似资料:
  • 主要内容:基本语法,删除触发器修改触发器可以通过删除原触发器,再以相同的名称创建新的触发器。 基本语法 与其他 MySQL 数据库对象一样,可以使用 DROP 语句将触发器从数据库中删除。 语法格式如下: DROP TRIGGER [ IF EXISTS ] [数据库名] <触发器名> 语法说明如下: 1) 触发器名 要删除的触发器名称。 2) 数据库名 可选项。指定触发器所在的数据库的名称。若没有指定,则为当前默认的数据库。

  • 我创建了一个触发器,其工作原理如下: 从表中删除数据后它将此行插入位于另一个数据库存档中的表中 我使用dblink在远程数据库中插入数据,问题是创建查询太难了,尤其是表包含20列以上,我想为10个其他表创建类似的函数。 有没有其他快速的方法来确保这项任务? 这里有一个很好的例子:

  • 本文向大家介绍Linux 创建修改删除用户和组的方法,包括了Linux 创建修改删除用户和组的方法的使用技巧和注意事项,需要的朋友参考一下 介绍 在日常的维护过程中创建用户操作用的相对会多一些,但是在这个过程中涉及到的知识点就不单单就是useradd了,接下来就来详细了解账号管理的相关信息。 用户信息 先从用户信息开始分析,可以通过查询/etc/password文件,每一行代表一个用户信息 每个冒

  • 我使用赛贝斯ASE 15.7。我希望在插入之前创建触发器,以便在插入之前,我想修改插入行中的一些字段。 请帮忙谢谢!

  • 29.3.3 创建和删除JPA数据库 默认情况下,仅当您使用内置数据库(H2、HSQL或Derby)时才会自动创建JPA数据库。您可以使用spring.jpa.*属性显式地配置JPA。例如,要创建和删除表,您可以将以下内容添加到application.properties中。 spring.jpa.hibernate.ddl-auto=create-drop Hibernate本身用于自动创建和

  • 问题内容: 我在不同的主机上有2个mysql数据库,想在将数据插入到另一个数据库后将触发器插入到另一个数据库中。我是mysql的新手,在sql server中我可以创建链接服务器并完成它。但是如何在mysql中做呢?两个数据库都有相似的表 问题答案: 为了能够继续进行此操作,必须首先确保两个服务器具有相同的配置。为了完成您想做的事情,可以在两个服务器上结合使用FEDERATED存储引擎和触发器,以