這個功能我是琢磨了好久,本來我的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 + '<' + @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 = '
set @xmlstr = @xmlstr + '
set @xmlstr = @xmlstr + '
set @xmlstr = @xmlstr + '
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,具體的用法網上有的可以查下,這只是我的一家之言,或許大家還有很好的實現,歡迎大家提意見啊!我知道這里很多大牛,可能我的想法會比較拙劣,但希望能夠幫助到大家,只此記錄我的技術成長歷程。
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com