在软件实施过程中,也许会有这样的问题: 表中数据出现非预期的结果,此时不确定是程序问题,哪个程序,存储过程,触发器.. 或还是人为修改的结果,此时可以用触发器对特定的表字段做跟踪监视,记录每次新增,修改,删除此字段值的操作详细信息(含登录名,主机名,IP地址,执行的TSQL语句,程序名等等), 以利于问题的排查.

-- 建测试表
CREATE TABLE sto
    (
        id INT NOT NULL, -- 主键字段
        de DATETIME -- 被跟踪的字段
            CONSTRAINT pk_sto
            PRIMARY KEY (id)
    );

-- 建日志表
CREATE TABLE log_sto
    (
        logid      INT          NOT NULL IDENTITY(1, 1), -- 日志序号(日志主键)
        operate    VARCHAR(10),                          -- 操作类型 如Insert,Update,Delete.
        id         INT,                                  -- 原表ID(主键)
        old_de     DATETIME,                             -- de字段旧值
        new_de     DATETIME,                             -- de字段新值
        spid       INT          NOT NULL,                -- spid
        login_name VARCHAR(100),                         -- 登录名
        prog_name  VARCHAR(100),                         -- 程序名
        hostname   VARCHAR(100),                         -- 主机名
        ipaddress  VARCHAR(100),                         -- IP地址
        runsql     VARCHAR(4000),                        -- 执行的TSQL代码
        UDate      DATETIME -- 操作日期时间
            CONSTRAINT pk_logsto
            PRIMARY KEY (logid)
    );
GO

-- 建跟踪触发器
CREATE TRIGGER tr_sto
ON sto
AFTER UPDATE, INSERT, DELETE
AS
    BEGIN
        DECLARE @di TABLE
            (
                et VARCHAR(200),
                pt VARCHAR(200),
                ei VARCHAR(MAX)
            );
        INSERT INTO @di
        EXEC ('dbcc inputbuffer(@@spid)');

DECLARE @op VARCHAR(10);
        SELECT
            @op = CASE WHEN EXISTS ( SELECT 1 FROM inserted ) AND EXISTS (SELECT 1 FROM deleted)
                            THEN 'Update'
                       WHEN EXISTS ( SELECT 1 FROM inserted ) AND NOT EXISTS (SELECT 1 FROM deleted)
                            THEN 'Insert'
                       WHEN NOT EXISTS(SELECT 1 FROM inserted ) AND EXISTS (SELECT 1 FROM deleted)
                          THEN 'Delete'
                  END;

IF @op IN (
                      'Update', 'Insert'
                  )
            BEGIN
                INSERT INTO log_sto
                    (
                        operate,
                        id,
                        old_de,
                        new_de,
                        spid,
                        login_name,
                        prog_name,
                        hostname,
                        ipaddress,
                        runsql,
                        UDate
                    )
                            SELECT
                                @op,
                                n.id,
                                o.de,
                                n.de,
                                @@spid,
                                (
                                    SELECT
                                        login_name
                                    FROM
                                        sys.dm_exec_sessions
                                    WHERE
                                        session_id = @@spid
                                ),
                                (
                                    SELECT
                                        program_name
                                    FROM
                                        sys.dm_exec_sessions
                                    WHERE
                                        session_id = @@spid
                                ),
                                (
                                    SELECT
                                        hostname
                                    FROM
                                        sys.sysprocesses
                                    WHERE
                                        spid = @@spid
                                ),
                                (
                                    SELECT
                                        client_net_address
                                    FROM
                                        sys.dm_exec_connections
                                    WHERE
                                        session_id = @@spid
                                ),
                                (
                                    SELECT TOP 1
                                        ISNULL(ei, '')
                                    FROM
                                        @di
                                ),
                                GETDATE()
                            FROM
                                inserted n
                                LEFT JOIN
                                    deleted o
                                        ON o.id = n.id;
            END;
        ELSE
            BEGIN
                INSERT INTO log_sto
                    (
                        operate,
                        id,
                        old_de,
                        new_de,
                        spid,
                        login_name,
                        prog_name,
                        hostname,
                        ipaddress,
                        runsql,
                        UDate
                    )
                            SELECT
                                @op,
                                o.id,
                                o.de,
                                NULL,
                                @@spid,
                                (
                                    SELECT
                                        login_name
                                    FROM
                                        sys.dm_exec_sessions
                                    WHERE
                                        session_id = @@spid
                                ),
                                (
                                    SELECT
                                        program_name
                                    FROM
                                        sys.dm_exec_sessions
                                    WHERE
                                        session_id = @@spid
                                ),
                                (
                                    SELECT
                                        hostname
                                    FROM
                                        sys.sysprocesses
                                    WHERE
                                        spid = @@spid
                                ),
                                (
                                    SELECT
                                        client_net_address
                                    FROM
                                        sys.dm_exec_connections
                                    WHERE
                                        session_id = @@spid
                                ),
                                (
                                    SELECT TOP 1
                                        ISNULL(ei, '')
                                    FROM
                                        @di
                                ),
                                GETDATE()
                            FROM
                                deleted o;
            END;
    END;
GO

--> 测试DML操作

-- 操作1
INSERT INTO sto
    (
        id,
        de
    )
VALUES
    (
        1, '2012-01-01 05:06:07'
    );
GO

-- 操作2
INSERT INTO sto
    (
        id,
        de
    )
VALUES
    (
        2, '2012-01-01 06:06:07'
    );
GO

-- 操作3
UPDATE
    sto
SET
    de = getdate()
WHERE
    id = 2;
GO

-- 操作4
UPDATE
    sto
SET
    de = getdate()
WHERE
    id = 1;
GO

-- 操作5
INSERT INTO sto
    (
        id,
        de
    )
VALUES
    (
        5, '2012-01-01 15:26:37'
    );
GO

-- 操作6
DELETE sto
WHERE
    id = 2;
GO

MSSQL记录表字段数据变化的相关SQl的更多相关文章

  1. ms_sql 触发器记录表字段数据变化的日志 -针对一张表操作

    create table sto (id int not null, -- 主键字段 de datetime -- 被跟踪的字段 constraint pk_sto primary key(id)) ...

  2. resultset 对象获取行字段数据时报:java.sql.SQLException: Column 'id' not found.

    resultset 对象获取行字段数据时报:java.sql.SQLException: Column 'id' not found. 代码: String sql="SELECT d.co ...

  3. 触发器记录表某一个字段数据变化的日志 包括插入insert 修改update 删除delete 操作

    本文参考:http://www.cnblogs.com/lyhabc/articles/3236985.html ,),  ),               ),           ),       ...

  4. Entity Framework使用EntityState和Attach来保存数据变化以及更新实体的个别字段

    在使用Entity Framework作为ORM来存取数据的过程中,最常规的操作就是对数据对象的更新.本文将会包含如何Attach Entity到一个数据Context中,以及如何使用EntitySt ...

  5. Sql Server 添加、更新、查询表注释、字段注释相关sql

    /*******************字段添加注释*********************/ if not exists (SELECT C.value AS column_description ...

  6. 小程序的数据监听 用法和vue中的watch一样====使用通配符监听所有自数据字段的变化

    使用通配符监听所有自数据字段的变化

  7. mssql与mysql 数据迁移

    概要: mssql向mysql迁移的实例,所要用到的工具bcp和load data local infile. 由于订单记录的数据是存放在mssql服务器上的,而项目需求把数据迁移到mysql ser ...

  8. MSSQL批量写入数据方案

    近来有一个项目Feature需要有批量写入数据的场景,正巧整理资料发现自己以前也类似实现的项目,在重构的同时把相关资料做了一个简单的梳理,方便大家参考. 循环写入(简单粗暴,毕业设计就这样干的)(不推 ...

  9. Adapter数据变化改变现有View的实现原理及案例

    首先说说Adapter详细的类的继承关系.例如以下图 Adapte为接口它的实现类的对象作为AdapterView和View的桥梁,Adapter是装载了View(比方ListView和girdVie ...

随机推荐

  1. 以opencv320和vs2013为例说明 vs路径配置方法

    =========================================== 新方法 ======================= 新方法的配置过程,路径之类的设置都是一样. 区别在于,在 ...

  2. Ultimate Chicken Horse GameProject第二次迭代成果文档

    基于上一次的迭代中的数据结构我们补充了UML图.用例图及状态图. 用例图:           选择游戏地图:玩家可以在本地游戏界面将角色移动到地图门口并按下E进入地图. 进行游戏用例: 选择并摆放道 ...

  3. 【转】HTTPS 如何保证数据传输的安全性?

    大家都知道,在客户端与服务器数据传输的过程中,HTTP协议的传输是不安全的,也就是一般情况下HTTP是明文传输的.但HTTPS协议的数据传输是安全的,也就是说HTTPS数据的传输是经过加密的. 在客户 ...

  4. Linux进程和计划任务管理

    1.笔记: 去掉头部:ps -aux - - no -heade 默认信号:15 强制:9 在命令前些一个nohup不再占用终端 date -s:修改时间 ntpdate pool.ntp.org:同 ...

  5. NLP之概率图模型

    1.概率图模型 概率图模型是一类用图来表达变量相关关系的概率模型,它以图为表示工具,最常见的是用一个结点表示一个或一组随机变量,结点之间的边表示变量间的概率相关关系.概率图模型可大致分为两类:第一类是 ...

  6. subprocess实用手册

    背景 python执行操作系统的命令,如python执行shell命令 subprocess模块主要用于创建子进程,并连接它们的输入.输出和错误管道,获取它们的返回状态.通俗地说就是通过这个模块,你可 ...

  7. dskms改为ckplayer播放器

    将ckplayer代码文件夹上传到/var/www/html/public/static/plugins/目录下修改/var/www/html/application/home/view/defaul ...

  8. GreenPlum 大数据平台--segment 失效问题恢复《二》(全部segment宕机情况下)

    01,情况描述 主Segment和它的镜像都宕掉.导致了greenplum数据库不可用状态 02,重启greenplum数据库 gpstop -r 03,恢复 gprecoverseg 04,状态检查 ...

  9. 【转】Python入门:Anaconda和Pycharm的安装和配置

    子曰:“工欲善其事,必先利其器.”学习Python就需要有编译Python程序的软件,一般情况下,我们选择在Python官网下载对应版本的Python然后用记事本编写,再在终端进行编译运行即可,但是对 ...

  10. luogu P1533 可怜的狗狗 |莫队+二分

    题目背景 小卡由于公务需要出差,将新家中的狗狗们托付给朋友嘉嘉,但是嘉嘉是一个很懒的人,他才没那么多时间帮小卡喂狗狗. 题目描述 小卡家有N只狗,由于品种.年龄不同,每一只狗都有一个不同的漂亮值.漂亮 ...