当前位置: 传客网 > 触发器实现记录操作表的日志

触发器实现记录操作表的日志

2017-01-09 作者:lylonggege

 这个功能我是琢磨了好久,本来我的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 + '<' + @pkname +'>';
  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_in  int 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 + '<' + @temp_pre_name + '>';
   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 = '<?xml version="1.0" encoding="gb2312" ?><root>';
set @xmlstr = @xmlstr + '<baseinfo>';
set @xmlstr = @xmlstr + '<opttag>' + convert(varchar(3),@opttype) + '</opttag>';
set @xmlstr = @xmlstr + '<opttab>' + @tabname + '</opttab>';
set @xmlstr = @xmlstr + '<pkname>' + @pk_pre_name + '</pkname>';
set @xmlstr = @xmlstr + '</baseinfo>';
set @xmlstr = @xmlstr + '<optinfo>';
set @xmlstr = @xmlstr + @optinfo;
set @xmlstr = @xmlstr + '</optinfo>';
set @xmlstr = @xmlstr + '</root>';

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,具体的用法网上有的可以查下,这只是我的一家之言,或许大家还有很好的实现,欢迎大家提意见啊!



相关推荐

  • [恶搞]List Control控件item的可编辑操作实现

    简介几乎每一个使用vc++编程的人,都将会遇到的列表控件。我们会遇到很多需要代表数据在多个栏目的列表控件场合。默认情况下是不可能的修改列表数据。在这个很小的文章我把一个简单的方法来实现在报告风格的列表控件编辑任意项目的值。这

  • 小表操作

    小表操作步骤实验二(开始即开始)电子二班高雅佳15050242004准备阶段:将桌面上的VB软件打开,如没有去程序中的附件中找到VB软件,双击VB软件,将VB软件调整到适合自己的大小。操作阶段:步骤一:点击屏幕左侧工具栏timer图标,在右

  • 【MySQL】三、数据库表操作

    数据库表操作:1.数据库表结构的复制CREATETABLEnew_tableLIKEoriginal_table;如果要将原来的数据也复制到新的表格中,使用INSERTINTOnew_tableSELECT*FROM 2.将搜索结

  • 一元多项式的加法以顺序表操作

    实验日期:2015/11/09一、实验题目线性表的顺序存储实现及其应用,给出一组数据要求实现一元多项式的加法运算,(9,12)(15,8)(3,2)(26,19)(-4,8)(-13,6)(82,0)​数据已排序;二、实验要求典

  • delphi 注册表操作(4)-另一种注册表操作类

    先前给了大家一个Tregistory现在用另一种类实现注册表读写usesRegistry;procedureTForm1.Button1Click(Sender:TObject);vard:string;e:treginifile;begi

  • Delphi2007 关于UAC的问题(注册表操作)

    <?xmlversion="1.0"encoding="UTF-8"standalone="yes"?><assemblyxmlns="urn:schemas-microsoft-com:asm.v1"manifestVe

  • 驱动注册表操作

    //------------------DeleteKey--------------------------------------------NTSTATUSstatus=STATUS_SUCCESS;HANDLEhSubKey;OBJ

  • 如何实现上位机同时与两台DSP实现双向通信呢,若是基于CAN总线的话麻烦给个实现的流程图及详细的实现步

    如何实现上位机同时与两台DSP实现双向通信呢,若是基于CAN总线的话麻烦给个实现的流程图及详细的实现步骤。以电脑得装linux系统,请问选哪个linux最好?包括红旗、红帽、ubuntu……不知道我说的对不对?最好详细说一下。申明一点,没有

  • 【赢在走势操盘日志】之2016年12月22日操作策略

    根据大盘走势定仓位,根据个股走势定买卖。市场永远是对的,只做市场追随者,不做市场预测者。免责声明:该操盘日志为私人操作日志,通过大盘走势分析,提示自己次日的操作策略。博主为短线操作风格,所以其仓位控制仅适合短线、超短线的仓位控制,不适合中长

  • SEO技术实践操作网站日志分析必杀技 

        前几天在SEO技术交流群里面看见有人在问为什么要看网站日志,网站日志怎么看,在群里问了一会都没有人答,最后还是一个群友给出了一些以往对日志分析的内容,所以笔者今天就来告诉一下还没有接触网站日志或者接触了网站日志,但是不知道怎么去分析

  • 搜索引擎优化的核心思想 实践操作之SEO技术网站日志分析

    内容简介:轻轻松松学seo,甲这里就以遂宁SEO博客的日志给大家展示一;乙商务搜索Baiduspider-ads;丙可是我们还是不知道网站日志长什么样的;丁分析网站日志的时候我们也只需要注意几个常;戊所以笔者今天就来告诉一下还没有接触网站日

  • 【欧声光操盘日志】中央经济工作会议对股市是长期利好

    【欧声光操盘日志】中央经济工作会议对股市是长期利好2016年12月19日(星期一)新浪网址http://blog.sina.com.cn/oushengguang(直接访问)(一)今日最新消息:1.各地正在加快落实中央经济工作会议精神;2.

  • 关于表彰2014年度“优秀操作技术能手”、“首席操作工”、 “一专多能人才等的决定

    关于表彰2014年度“优秀操作技术能手”、“首席操作工”、“一专多能人才”等的决定2014年,平棉集团公司在一线职工中开展了“操作技术比武”和评选“首席操作工”、“一专多能人才”、“质量标兵”、“合理化建议、小改小革、技术革新”等竞赛活动。

  • seo搜索引擎优化秘籍 SEO技术实践操作网站日志分析必杀技

    核心提示:学好seo可以干嘛,①〉准确的说法应该是WEB服务器日志;②〉视频搜索Baiduspider-vide;③〉200是网站的返回码;④〉2014-07-29;⑤〉访问状态是

  • PHP+Mysql+jQuery实现查询和列表框选择操作

    Oct12PHP+Mysql+jQuery实现查询和列表框选择操作helloweba.comAuthor:月光光Time:2010-10-1213:39Tag:phpajaxjquery本文讲解如何通过ajax查询mysql数据,并将返回的

  • 怎么学好SEO优化SEO技术实践操作网站日志分析必杀技

    本文摘要:如何快速学SEO优化一〉接下来我们在看看网站日志长什么样;二〉这个是百度的联盟的spider;三〉所以笔者今天就来告诉一下还没有接触网站日;四〉相信聪明的小伙伴已经知道;五〉但是不知道怎么去分析的小伙伴们;六〉04:23:14;七

  • 【维护电脑·谨慎操作注册表·深入浅出】

    1、Windows操作系统的注册表程序是系统的中区神经,安装软件或者更新补丁等一系列操作,会在注册表里留下重要的讯息,这款软件安装在哪个路径,需要什么环境支持等。对新手而言,修改注册表等操作还是需要谨慎处置,必须操作,事前可做好注册表的备份

  • python 以单例模式封装logging相关api实现日志打印类

    python以单例模式封装logging相关api实现日志打印类by:授客QQ:1033553122测试环境:Python版本:Python2.7实现功能:支持自由配置,如下log.conf,1)可以配置日志文件路径(log_file);2

  • 转--oracle日志操作模式(归档模式和非归档模式)

    在Oracle数据库中,主要有两种日志操作模式,分别为非归档模式与归档模式。默认情况下,数据库采用的是非归档模式。作为一个合格的数据库管理员,应当深入了解这两种日志操作模式的特点,并且在数据库建立时,选择合适的操作模式。笔者今天就谈谈自己对

  • 【第3册】第14课  书写日志话家乡

    课题第14课书写日志话家乡课时第一课时教学内容能在个人空间中写日志、发表日志,并对日志进行分类。能关注好友,并对好友的日志发表评论。教学目标知识技能【1】能在个人空间中写日志、发表日志,并对日志进行分类。【2】能关注好友,并对好友的日志发表

返回
顶部