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


    这个功能我是琢磨了好久,本来我的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,具体的用法网上有的可以查下,这只是我的一家之言,或许大家还有很好的实现,欢迎大家提意见啊!
  • 相关阅读:
    通过actionlib控制jaco机械臂
    actionlib学习
    配置 jaco机械臂 ros环境
    ubuntu14.04标题栏显示上下网速
    linux下alsa架构音频驱动播放wav格式文件
    ros语音交互(五)移植科大讯飞语音识别到ros
    ubuntu14.04 wifi驱动
    Ubuntu14.04使用apt-fast来加快apt-get下载的教程
    ROS语音交互(四)接入图灵语义理解
    相比传统游戏,区块链游戏的价值在哪里?
  • 原文地址:https://www.cnblogs.com/ruishuang208/p/4242133.html
Copyright © 2020-2023  润新知