触发器实现操作日志

    xiaoxiao2021-11-02  65

    原址http://blog.sina.com.cn/s/blog_702252fd0101guib.html

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

      (2013-03-17 11:13:22) 转载 标签: 

    sqlserver

     

    触发器

     

    日志

    分类: IT

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

    转载请注明原文地址: https://ju.6miu.com/read-677939.html

    最新回复(0)