SQL Server实现用触发器捕获DML操作的会话信息【实例】

需求背景

上周遇到了这样一个需求,维护人员发现一个表的数据经常被修改,由于历史原因;文档缺少;以及维护人员的经常变更,导致他们对系统也业务也不完全熟悉,他们也不完全清楚哪些系统和应用程序会对这个表的数据进行操作。现在他们想找出有哪些服务器,哪些应用程序会对这个表进行INSERT、UPDATE操作。那么问题来了,怎么去解决这个问题呢?

解决方案

由于数据库版本是标准版,我们选择了使用触发器来捕获进行DML操作的会话的相关信息,例如,Host_Name、Program_Name等 ,选择触发器是因为简单直接。我们先创建一个表名为TEST的表,假设我们想监控有哪些应用服务器,以及那些应用程序会对表TEST进行INSERT、UPDATE操作。

USE [AdventureWorks2014]

GO

IF NOT EXISTS (SELECT 1 FROM sys.sysobjects WHERE id=object_id(N'[dbo].[TEST]') AND OBJECTPROPERTY(id, N'IsTable')=1 )

BEGIN

CREATE TABLE [dbo].[TEST](

  [OBJECT_ID] [INT] NOT NULL,

  [NAME] [VARCHAR](8) NULL,

  CONSTRAINT PK_TEST  PRIMARY KEY (OBJECT_ID)

) 

END

GO

INSERT INTO dbo.TEST

SELECT 1, 'kerry' UNION ALL

SELECT 2, 'jimmy'

那么我们接下来在表上面新增几个字段 [HOST_NAME]、[PROGRAM_NAME]、LOGIN_NAME用来记录最后一次修改该记录的会话信息,另外创建触发器TRG_TEST来更新这几个字段

ALTER TABLE TEST ADD [HOST_NAME] NVARCHAR(256)

ALTER TABLE TEST ADD [PROGRAM_NAME] NVARCHAR(256);

ALTER TABLE TEST ADD LOGIN_NAME NVARCHAR(256);

CREATE TRIGGER TRG_TEST ON dbo.TEST AFTER 

INSERT,UPDATE

AS 

IF (EXISTS(SELECT 1 FROM INSERTED))

BEGIN

  UPDATE dbo.TEST

  SET   dbo.TEST.[HOST_NAME] = ( SELECT host_name

                   FROM  sys.dm_exec_sessions

                   WHERE session_id = @@SPID

                  ) ,

      dbo.TEST.PROGRAM_NAME = ( SELECT  program_name

                   FROM   sys.dm_exec_sessions

                   WHERE   session_id = @@SPID

                  ) ,

      dbo.TEST.LOGIN_NAME = ( SELECT login_name

                  FROM  sys.dm_exec_sessions

                  WHERE  session_id = @@SPID

                 )

  FROM  dbo.TEST t

      INNER JOIN INSERTED i ON t.OBJECT_ID = i.OBJECT_ID

END

GO

接下来,我们来简单测试一下,如下所示,分布插入、更新一条记录

INSERT INTO dbo.TEST(OBJECT_ID,NAME)

SELECT 3,'ken'

UPDATE dbo.TEST SET NAME='Richard' WHERE OBJECT_ID=2;

如下所示,因为我只是用SSMS更新,插入数据,所以捕获的是Microsoft SQL Server Management Studio - Query。

这这种方式还有一个弊端,那就是如果应用程序的SQL,写得不够健壮的话,那么增加字段就会导致以前的应用程序出现问题,例如,应用程序有下面这样的SQL,增加字段后,它就会报错。

INSERT INTO dbo.TEST

SELECT 3,'ken'

所以这种方案不太可行,会增加应用程序出现Bug的风险。那么其实我们可以新建一个表,每当原表TEST有INSERT、UPDATE操作时,通过触发器捕获会话进程信息,然后插入该表(注意,新建的表包含源表的主键字段,例如这里TEST的主键字段为OBJECT_ID,那么我们下面就包含OBJECT_ID)

USE [AdventureWorks2014]

GO

DROP TABLE dbo.[TRG_TEST_SESSION_INFO];

GO

IF NOT EXISTS (SELECT 1 FROM sys.sysobjects WHERE id=object_id(N'[dbo].[TRG_TEST_SESSION_INFO]') AND OBJECTPROPERTY(id, N'IsTable')=1 )

BEGIN

CREATE TABLE [TRG_TEST_SESSION_INFO](

  [ID]        INT NOT NULL IDENTITY(1,1),

  [OBJECT_ID]    INT,

  [HOST_NAME]    NVARCHAR(256),

  [PROGRAM_NAME]   NVARCHAR(256),

  [LOGIN_NAME]    NVARCHAR(256),

  CONSTRAINT PK_TRG_TEST_SESSION_INFO  PRIMARY KEY (ID)

) 

END

GO

CREATE TRIGGER TRG_TEST_SESSION ON dbo.TEST

AFTER INSERT ,UPDATE

AS

IF (EXISTS(SELECT 1 FROM INSERTED))

BEGIN

  /*

  INSERT INTO dbo.[TRG_TEST_SESSION_INFO]

  SELECT (SELECT I.OBJECT_ID FROM INSERTED I), HOST_NAME,program_name,login_name

                   FROM  sys.dm_exec_sessions

                   WHERE session_id = @@SPID*/

  INSERT INTO dbo.[TRG_TEST_SESSION_INFO]

  SELECT I.OBJECT_ID, S.HOST_NAME,S.PROGRAM_NAME,S.LOGIN_NAME

                   FROM  sys.dm_exec_sessions s,

                      Inserted i

                   WHERE session_id = @@SPID

END

GO

在运行一小段时间后,如果已经找出了哪些服务器、哪些应用程序会对这些表操作后,那么就必须马上删除这些表和触发器,避免长时间运行,影响性能。

以上这篇SQL Server实现用触发器捕获DML操作的会话信息【实例】就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • SQLServer2005触发器提示其他会话正在使用事务的上下文的解决方法

    MSDN上看了一下说是sql server 2005不支持在分布式事务处理中存在指向本地的链接服务器(环回链接服务器)个人尝试了下是由于在双向的sql server访问中采用了链式方式访问(LinkedServer方式),遇到这种情况只需要将原来访问对方数据库的语句: 复制代码 代码如下: select  *  from  linkedServerA.dbo.table1 修改为: 复制代码 代码如下: select  *  from  dbo.table1 即可. 触发器代码如下: 复制代码

  • SqlServer触发器详解

    触发器(trigger)是SQL server 提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊的存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触发,比如当对一个表进行操作( insert,delete, update)时就会激活它执行. 触发器经常用于加强数据的完整性约束和业务规则等. 触发器可以从 DBA_TRIGGERS ,USER_TRIGGERS 数据字典中查到.SQL3的触发器是一个能由系统自动执行对数据库修改的语句. 触发器可以查询其他表,

  • SQL SERVER中各类触发器的完整语法及参数说明

    语法: Trigger on an INSERT, UPDATE, or DELETE statement to a table or view (DML Trigger) CREATE TRIGGER [ schema_name . ]trigger_name ON { table | view } [ WITH <dml_trigger_option> [ ,...n ] ] { FOR | AFTER | INSTEAD OF } { [ INSERT ] [ , ] [ UPDATE

  • SQL Server实现用触发器捕获DML操作的会话信息【实例】

    需求背景 上周遇到了这样一个需求,维护人员发现一个表的数据经常被修改,由于历史原因:文档缺少:以及维护人员的经常变更,导致他们对系统也业务也不完全熟悉,他们也不完全清楚哪些系统和应用程序会对这个表的数据进行操作.现在他们想找出有哪些服务器,哪些应用程序会对这个表进行INSERT.UPDATE操作.那么问题来了,怎么去解决这个问题呢? 解决方案 由于数据库版本是标准版,我们选择了使用触发器来捕获进行DML操作的会话的相关信息,例如,Host_Name.Program_Name等 ,选择触发器是因为

  • VS连接SQL server数据库及实现基本CRUD操作

    目录 连接数据库 使用dataGridView控件显示表中的数据. 实现基本CRUD操作 总结 连接数据库 打开vs,点击 视图,打开sql资源管理器,添加SQL Server 输入服务器名称,用户名,密码,进行连接. 如图,就可以看到vs已经连接到了自己的数据库,class和song两个数据库 .可以看到class下面有五个表. 查看其中一个SC表,数据显示正常,证明已连接. 使用dataGridView控件显示表中的数据. 在工具箱中找到dataGridView控件拖入Form1中,如图:

  • 浅谈SQL Server中的三种物理连接操作(性能比较)

    在SQL Server中,我们所常见的表与表之间的Inner Join,Outer Join都会被执行引擎根据所选的列,数据上是否有索引,所选数据的选择性转化为Loop Join,Merge Join,Hash Join这三种物理连接中的一种.理解这三种物理连接是理解在表连接时解决性能问题的基础,下面我来对这三种连接的原理,适用场景进行描述. 嵌套循环连接(Nested Loop Join) 循环嵌套连接是最基本的连接,正如其名所示那样,需要进行循环嵌套,嵌套循环是三种方式中唯一支持不等式连接的

  • SQL Server重置IDENTITY属性种子值操作

    SQL Server重置IDENTITY属性种子值 -- IDENTITY重置种子 DBCC CHECKIDENT(表名, RESEED, 0) 补充:sql server 修改IDENTITY 字段 的统计当前值 一个表数据是从另一服务器同步过来的.现在数据已超过了 3514万条,但插入值时,提示不能插入重复键值 320. 查看表的统计时间,看到是N年前统计的. 手工更新表统计信息: UPDATE STATISTICS TABLE_NAME, 再插入,还是无效. 后使用代码: DBCC CHE

  • SQL Server怎么找出一个表包含的页信息(Page)

    前言 在SQL Server中,如何找到一张表或某个索引拥有那些页面(page)呢? 有时候,我们在分析和研究(例如,死锁分析)的时候还真有这样的需求,那么如何做呢? SQL Server 2012提供了一个无文档的DMF(sys.dm_db_database_page_allocations)可以实现我们的需求,sys.dm_db_database_page_allocations有下面几个参数: @DatabaseId:    数据库的ID,可以用DB_ID()函数获取某个数据库或当前数据库

  • SQL Server Table中XML列的操作代码

    复制代码 代码如下: --创建测试表 DECLARE @Users TABLE ( ID INT IDENTITY(1,1), UserInfo XML ) ---插入测试数据 DECLARE @xml XML SET @xml=' <root> <user> <userid>1</userid> <userName>test1</userName> </user> </root>' INSERT INTO @

  • ORACLE中查找定位表最后DML操作的时间小结

    在Oracle数据库中,如何查找,定位一张表最后一次的DML操作的时间呢? 方式有三种,不过都有一些局限性,下面简单的解析.总结一下. 1:使用ORA_ROWSCN伪列获取表最后的DML时间 ORA_ROWSCN伪列是Oracle 10g开始引入的,可以查询表中记录最后变更的SCN.然后通过SCN_TO_TIMESTAMP函数可以将SCN转换为时间戳,从而找到最后DML操作时SCN的对应时间.但是,默认情况下,每行记录的ORA_ROWSCN是基于Block的,除非在建表的时候开启行级跟踪. SE

  • SQL Server触发器及触发器中的事务学习

    如果你有对触发器和事务的概念,有些了解,这篇文章,对你来说会是很简单,或能让你更进一步的了解触发器里面的一些故事,和触发器中事务个故事.在这边文章里面,我不会从触发器和事务的概念去讲述,而是从常见的两种触发器类型(DML触发器 & DDL触发器)和After触发器 &  Instead Of 触发器的应用不同,开始说起它们,然后是说与事务有关的故事.如果,你有什么建议和意见,都可以通过文章后面的回复与我沟通,或者通过E-Mail方式,与 我交流:我的Email地址是:glal@163.co

  • 深入浅析SQL Server 触发器

    触发器是一种特殊类型的存储过程,它不同于之前的我们介绍的存储过程.触发器主要是通过事件进行触发被自动调用执行的.而存储过程可以通过存储过程的名称被调用. Ø 什么是触发器 触发器对表进行插入.更新.删除的时候会自动执行的特殊存储过程.触发器一般用在check约束更加复杂的约束上面.触发器和普通的存储过程的区别是:触发器是当对某一个表进行操作.诸如:update.insert.delete这些操作的时候,系统会自动调用执行该表上对应的触发器.SQL Server 2005中触发器可以分为两类:DM

随机推荐