MSSQL记录表字段数据变化的相关SQl
在软件实施过程中,也许会有这样的问题: 表中数据出现非预期的结果,此时不确定是程序问题,哪个程序,存储过程,触发器.. 或还是人为修改的结果,此时可以用触发器对特定的表字段做跟踪监视,记录每次新增,修改,删除此字段值的操作详细信息(含登录名,主机名,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的更多相关文章
- ms_sql 触发器记录表字段数据变化的日志 -针对一张表操作
create table sto (id int not null, -- 主键字段 de datetime -- 被跟踪的字段 constraint pk_sto primary key(id)) ...
- resultset 对象获取行字段数据时报:java.sql.SQLException: Column 'id' not found.
resultset 对象获取行字段数据时报:java.sql.SQLException: Column 'id' not found. 代码: String sql="SELECT d.co ...
- 触发器记录表某一个字段数据变化的日志 包括插入insert 修改update 删除delete 操作
本文参考:http://www.cnblogs.com/lyhabc/articles/3236985.html ,), ), ), ), ...
- Entity Framework使用EntityState和Attach来保存数据变化以及更新实体的个别字段
在使用Entity Framework作为ORM来存取数据的过程中,最常规的操作就是对数据对象的更新.本文将会包含如何Attach Entity到一个数据Context中,以及如何使用EntitySt ...
- Sql Server 添加、更新、查询表注释、字段注释相关sql
/*******************字段添加注释*********************/ if not exists (SELECT C.value AS column_description ...
- 小程序的数据监听 用法和vue中的watch一样====使用通配符监听所有自数据字段的变化
使用通配符监听所有自数据字段的变化
- mssql与mysql 数据迁移
概要: mssql向mysql迁移的实例,所要用到的工具bcp和load data local infile. 由于订单记录的数据是存放在mssql服务器上的,而项目需求把数据迁移到mysql ser ...
- MSSQL批量写入数据方案
近来有一个项目Feature需要有批量写入数据的场景,正巧整理资料发现自己以前也类似实现的项目,在重构的同时把相关资料做了一个简单的梳理,方便大家参考. 循环写入(简单粗暴,毕业设计就这样干的)(不推 ...
- Adapter数据变化改变现有View的实现原理及案例
首先说说Adapter详细的类的继承关系.例如以下图 Adapte为接口它的实现类的对象作为AdapterView和View的桥梁,Adapter是装载了View(比方ListView和girdVie ...
随机推荐
- 05-人脸识别-FaceNet的感性认识
源码链接:https://github.com/davidsandberg/facenet 论文链接:https://arxiv.org/pdf/1503.03832.pdf B站大神视频解读论文:h ...
- 通过DatagramSocket实现UDP编程(十三)
原文链接:https://www.cnblogs.com/hysum/p/7533149.html UDP通信: UDP协议(用户数据报协议)是无连接.不可靠.无序的. UDP协议以数据报作为数据传输 ...
- http协议里定义的四种常见数据的post方法
原文 https://blog.csdn.net/charlene0824/article/details/51199292 关于http协议里定义的四种常见数据的post方法,分别是: applic ...
- JS中的箭头函数与this
转载自:https://juejin.im/post/5aa1eb056fb9a028b77a66fd#heading-1 JavaScript在ES6语法中新增了箭头函数,相较于传统函数,箭头函数不 ...
- ABP 不包裹返回的数据
告诉abp不包裹返回的数据,返回的数据是什么 就是什么 不用再多包裹一次了. 用在 如:别人需要你提供接口 且给你指定了返回的数据结构. 源码:
- 挂载ESP(EFI)分区到Windows,并让资源管理器有权限读写
如果你的磁盘精灵经常原地自爆,但你又想读写ESP分区的文件,那么请看此贴 1 //例子如下 diskpart //运行Diskpart工具 list disk //列出所有磁盘 sel disk // ...
- python的import和form...import的区别
import和form...import的区别 参考链接 骏马金龙 https://www.cnblogs.com/lzc978/p/10105194.html 普通区别 import 使用impor ...
- 转: 彻底理解 Spring 容器和应用上下文
本文由 简悦 SimpRead 转码, 原文地址 https://mp.weixin.qq.com/s/o11jVTJRsBi998WlgpfrOw 有了 Spring 之后,通过依赖注入的方式,我们 ...
- 【1】hexo+github搭建个人博客的过程记录
前提: 1.新建一个github仓库 2.安装配置Node.js 3.安装配置Git 前提 步骤1.新建一个github仓库 打开github网站,(注册)登录账号,新建一个仓库; 注:仓库名称要求, ...
- java8时间处理实例
实例: package com.javaBase.time; import java.time.Clock; import java.time.LocalDate; import java.time. ...