在软件实施过程中,也许会有这样的问题: 表中数据出现非预期的结果,此时不确定是程序问题,哪个程序,存储过程,触发器.. 或还是人为修改的结果,此时可以用触发器对特定的表字段做跟踪监视,记录每次新增,修改,删除此字段值的操作详细信息(含登录名,主机名,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. OpenStack产品摘要

    docs OpenStack 核心服务 计算 Nova:虚拟化设施资源管理 ZUN:容器管理 QINLING:Serveless Function 裸金属 IRONIC:裸金属资源管理 CYBORDF ...

  2. maven warnning 'build.plugins.plugin.version' is missing

    裝完maven后,package或clean时出错:[WARN] [WARN] Some problems were encountered while building the effective ...

  3. Sentinel: 分布式系统的流量防卫兵

    前言 在 Spring Cloud 体系中,熔断降级我们会使用 Hystrix 框架,限流通常会在 Zuul 中进行处理,Zuul 中没有自带限流的功能,我们可以自己做限流或者集成第三方开源的限流框架 ...

  4. ES方法使用注意

    matchQuery:会将搜索词分词,再与目标查询字段进行匹配,若分词中的任意一个词与目标字段匹配上,则可查询到.   termQuery:不会对搜索词进行分词处理,而是作为一个整体与目标字段进行匹配 ...

  5. IDEA 最新破解方法,2019 版本已支持(持续更新,更新时间2019-05-14)

    一.安装进入官网下载适合自己系统的版本,下载地址:https://www.jetbrains.com/idea/download/#section=windows ​ 2. 安装中选择适合本机的64位 ...

  6. SQL ------------ avg() 与 sum 函数

    AVG() 函数返回数字列的平均值 注意是数字的平均数, 语法: select avg(字段) from 表名 建个表,弄点数据 使用 select avg(字段) as 平均数 from 表名 与w ...

  7. useEffect传入第二个参数陷入死循环

    最近新项目刚上手,就用了react的hooks,之前也看过hooks的不少文章,只是还没实战实战. 业务场景1:需要在页面一开始时得到一个接口的返回值,取调用另一个接口. 我的思路是,先设置这个接口的 ...

  8. 如何在同一行里执行多个linux命令?

    如果前一个命令能够成功执行,那么可以使用"&&"操作符(引号内)来合并多个后续的命令. 举例: cd /my_folder && rm *.jar ...

  9. Java ReentrantLock中tryLock与lock的区别(非公平锁与公平锁)

    设置同步状态,利用CAS操作. // CAS操作:如果当前状态值等于期望值,则自动将同步状态设置为给定的更新值 protected final boolean compareAndSetState(i ...

  10. windows远程桌面无法拷贝文件的问题与解决方法

    在开发完往windows服务器上部署系统或者给系统打补丁的时候,都会需要远程桌面的双向拷贝文件功能. 但是有些时候却会发现没有办法拷贝文件,原因主要有两个. 01 远程桌面的剪贴板设置 一个是在远程桌 ...