mysql 触发器 sql日志_触发器实现记录操作表的日志
这个功能我是琢磨了好久,本来我的sqlserver方面的知识深入了解的就不多,关键的难点是用变量代替字段名,然后获取字段在表中存的值,再赋给另外一个变量,我之所以这么做,因为后面好几处要用到这个字段的名称,我才用变量代替,便于修改,可就是 实现 花费
这个功能我是琢磨了好久,本来我的sqlserver方面的知识深入了解的就不多,关键的难点是用变量代替字段名,然后获取字段在表中存的值,再赋给另外一个变量,我之所以这么做,因为后面好几处要用到这个字段的名称,我才用变量代替,便于修改,可就是实现花费了很长时间,网上这么方面的资料又少,可终究还是找到了解决方案,希望大家以后遇到同样的问题不至于头大,把具体的实现分享给大家
CREATE trigger [dbo].[trg_new_course]
on [dbo].[course]
for insert,delete,update
as
begin
declare @tabname varchar(50),
@pkname varchar(20),
@pkvalue varchar(20),
@opttype int,
@optip varchar(20),
@optsql varchar(200),
@xmlstr nvarchar(500);
declare @optinfo nvarchar(500), @id_i int, @id_d int;
declare @min_id int, --最小的字段号
@total int, --记录总数
@row_count int, --循环变量
@temp_name varchar(100), --临时字段名
@temp_pre_name varchar(100), --带字段类型前缀的变量
@temp_type varchar(100), --临时字段类型
@temp_value varchar(100), --临时字段值
@xmlnode_value varchar(100), --xml的节点值
@sql_name varchar(100), --sql操作相关的字段
@sql_value varchar(100), --sql操作相关的字段值
@sql nvarchar(200), --存储动态
sql @pk_pre_name varchar(20) --带类型前缀的关键字段名
set @sql_name = '';
set @sql_value = '';
set @row_count = 1;
set @pkname = 'id'; --关键字名称
set @tabname = 'course'; --操作的表名
set @optinfo = '';
select @id_i=id from inserted; select @id_d=id from deleted;
select @temp_type = data_type from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @tabname and column_name = @pkname;
if (@temp_type = 'int')
begin
set @pk_pre_name = 'i' + @pkname
end
else if(@temp_type = 'float')
begin
set @pk_pre_name = 'f' + @pkname
end
else if(@temp_type = 'decimal')
begin
set @pk_pre_name = 'd' + @pkname
end
else if(@temp_type = 'datetime')
begin
set @pk_pre_name = 'da' + @pkname
end
else
begin
set @pk_pre_name = 'c' + @pkname
end
if @id_i is null and @id_d is not null --删除操作
begin
set @pkvalue = @id_d;
set @opttype = 1;
--若变量的类型不是字符串型
set @pkvalue = convert(varchar(200),@pkvalue);
--生成执行删除操作的sql语句
set @optsql = 'delete from ' + @tabname + ' where ' + @pkname + '=' + @pkvalue;
--生成删除操作字段信息的xml表示
set @optinfo = @optinfo + '';
set @optinfo = @optinfo + @pkvalue;
set @optinfo = @optinfo + '' + @pkname +'>';
end
else
begin
set @pkvalue = @id_i;
select * into temps from inserted;--这句必须写动态sql中时找不到inerted这个逻辑表的
select @min_id = max(ordinal_position) from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @tabname;
select @total = count(1) from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @tabname;
while(@row_count <= @total)
begin
select @temp_name = column_name,@temp_type = data_type from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @tabname and ordinal_position = @min_id;
if(@temp_type = 'int')
begin
declare @temp_in int;
SET @sql = 'select @temp_in = ' + @temp_name + ' from temps;';
EXEC SP_EXECUTESQL @Sql, N'@temp_inint OUTPUT', @temp_in OUTPUT;
set @xmlnode_value = convert(varchar(100),@temp_in);
set @temp_value = @xmlnode_value;
set @temp_pre_name = 'i' + @temp_name;
end
else if(@temp_type = 'float')
begin
declare @temp_inf float;
SET @sql = 'select @temp_inf = ' + @temp_name + ' from temps;';
EXEC SP_EXECUTESQL @Sql, N'@temp_inf float OUTPUT', @temp_inf OUTPUT;
set @xmlnode_value = convert(varchar(100),@temp_inf);
set @temp_value = @xmlnode_value;
set @temp_pre_name = 'f' + @temp_name;
end
else if(@temp_type = 'decimal')
begin
declare @temp_ind float;
SET @sql = 'select @temp_ind = ' + @temp_name + ' from temps;';
EXEC SP_EXECUTESQL @Sql, N'@temp_ind decimal(18,0) OUTPUT', @temp_ind OUTPUT;
set @xmlnode_value = convert(varchar(100),@temp_ind);
set @temp_value = @xmlnode_value;
set @temp_pre_name = 'd' + @temp_name;
end
else
begin
declare @temp_inc varchar(200);
SET @sql = 'select @temp_inc = ' + @temp_name + ' from temps;';
EXEC SP_EXECUTESQL @Sql, N'@temp_inc varchar(200) OUTPUT', @temp_inc OUTPUT;
set @xmlnode_value = convert(varchar(100),@temp_inc);
set @temp_value = '''' + @xmlnode_value + '''';
set @temp_pre_name = 'c' + @temp_name;
end
--生成插入/修改操作相关数据信息的xml表示
set @optinfo = @optinfo + '';
set @optinfo = @optinfo + @xmlnode_value;
set @optinfo = @optinfo + '' + @temp_pre_name + '>';
if @id_i is not null and @id_d is null -- 插入操作
begin
--生成插入操作执行的sql语句
if(@temp_name <> @pkname)
begin
set @sql_name = @sql_name + ',' + @temp_name;
set @sql_value = @sql_value + ',' + @temp_value;
end
end
else if @id_i is not null and @id_d is not null --更新操作
begin
--生成修改操作执行的sql语句
if(@temp_name <> @pkname)
begin
set @sql_name = @sql_name + ',' + @temp_name + '=' + @temp_value;
end
end
select @min_id = ordinal_position from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'course' and ordinal_position < @min_id;
set @row_count = @row_count + 1;
end
if @id_i is not null and @id_d is null -- 插入操作
begin
--生成执行插入操作的sql语句
set @opttype = 0;
set @optsql = 'insert into ' + @tabname + '(' + substring(@sql_name,2,len(@sql_name)) + ')' + ' values(' + substring(@sql_value,2,len (@sql_value)) +')';
end
else if @id_i is not null and @id_d is not null --更新操作
begin
--生成执行修改操作的sql语句
set @opttype = 3;
set @optsql = 'update ' + @tabname + ' set ' + substring(@sql_name,2,len(@sql_name)) + ' where ' + @pkname + '=' + @pkvalue;
end
drop table temps;
end
set @xmlstr = '';
set @xmlstr = @xmlstr + ''; set @xmlstr = @xmlstr + '' + convert(varchar(3),@opttype) + '';
set @xmlstr = @xmlstr + '' + @tabname + '';
set @xmlstr = @xmlstr + '' + @pk_pre_name + '';
set @xmlstr = @xmlstr + ''; set @xmlstr = @xmlstr + '';
set @xmlstr = @xmlstr + @optinfo;
set @xmlstr = @xmlstr + '';
set @xmlstr = @xmlstr + '';
select @optip=client_net_address from sys.dm_exec_connections where Session_id=@@spid;
if(@pkvalue is null)
begin
set @pkvalue = -1;
end
insert into optlog values(@tabname,@pkname,@pkvalue,@opttype,@optip,getdate(),@optsql,@xmlstr);
print '操作执行成功';
end
红色标注的部分我认识是实现的难点,就是用到了sqlserver的系统存储过程sp_executesql,具体的用法网上有的可以查下,这只是我的一家之言,或许大家还有很好的实现,欢迎大家提意见啊!我知道这里很多大牛,可能我的想法会比较拙劣,但希望能够帮助到大家,只此记录我的技术成长历程。
本文原创发布php中文网,转载请注明出处,感谢您的尊重!
mysql 触发器 sql日志_触发器实现记录操作表的日志相关推荐
- 一文搞懂Java日志级别,重复记录、丢日志问题
1 SLF4J 日志行业的现状 框架繁 不同类库可能使用不同日志框架,兼容难,无法接入统一日志,让运维很头疼! 配置复杂 由于配置文件一般是 xml 文件,内容繁杂!很多人喜欢从其他项目或网上闭眼co ...
- mysql 慢sql分析_如何分析Mysql慢SQL
内容摘要: 开启慢查询日志捕获慢SQL 使用explain分析慢SQL 使用show profile查询SQL执行细节 常见的SQL语句优化 一.开启慢查询日志捕获慢SQL ① 查询mysql是否开启 ...
- java运行异常日志_使用log4j记录Java中的运行时异常
小编典典 我不确定这是否是您要寻找的,但是有一个终止线程的异常处理程序.它是线程异常未明确捕获的任何异常的处理程序. 默认"未捕获的异常处理程序"只是调用printStackTra ...
- python代码执行过程记录_优雅的记录Python程序日志
1 本篇概要 logging模块的调用: 保存log日志为文件: 调整输入日志等级: 修改日志消息格式: 2 前言 在使用Python编写程序的过程中,我们经常使用print()函数打印一些信息到控制 ...
- ios 打印 详细错误日志_关于Xcode不能打印崩溃日志
最近在调试应用的时候发现了一个问题, 就是Xcode的控制台不打印Crash日志. 几经周折终于发现了问题. 因为不能打印日志, 开始以为是我没有设置 NSSetUncaughtExceptionHa ...
- 板卡上的日志缓冲区只可以记录1000条日志,当超过1000条记录时,新增的日志将覆盖旧的记录(是最旧的记录)
王晓华前辈在"一个队列引发的惨案"一节中,说到用循环队列处理固定长度缓冲区问题,小僧读到这里,深深一惊,不禁感叹算法与数据结构结合的巧妙!!!也许是因为小僧是菜鸟,也许是因为小僧少 ...
- mysql触发器实现+备份_触发器+脚本备份单表数据
原理: 1.备份方法:使用mysql的select ... into outfile将表的数据导出成外部文件进行备份 2.备份时机:在表中设置触发器,当有增删改事务提交时就执行备份方法 3.关键问题: ...
- mysql 触发器拼接字符串_触发器 字符串拼接函数
##触发器 触发时间 before after 触发事件 insert update delete 等 create table score_log select * from score where ...
- mysql原生sql语句_原生SQL语句
-- -sql语句的注意 : 1 以;作为结束符 2不区分大小写--01mysql 数据库的操作--链接数据库 mysql-uroot -pmysql--不显示密码 mysql-uroot -p my ...
最新文章
- 远程过程调用RPC简介
- linux 查看日志信息--less命令
- 实战SSM_O2O商铺_31【商品】商品添加之View层的实现
- 与nlp相关的模型概览
- 在Spring中使用多个动态缓存
- php连接函数config,smarty内置函数config_load用法实例
- sql 批量插入数据到Sqlserver中 效率较高的方法
- c/c++再学习:C与Python相互调用
- vue项目中axios请求网络接口封装
- Python的发展前景在哪?怎么样让Python程序员持续发展?
- SMC真空电磁阀气路接法
- idea中svn颜色代表的文件状态
- c语言四则运算去括号,四年级四则运算交换律、结合律、分配律及去括号公式汇总,附例子!...
- java 背单词系统_基于JAVA模拟背单词系统(含源文件)
- 撤消 git rebase
- springboot框架图解
- TweenMax逐帧动画
- 关于计算机的想象作文550字,想象作文550字:未来的一天
- javascript 实现在线多币种汇率实时换算
- 数据库原理与设计P163习题9答案