昨天在进行系统升级中,对于某些程序生成的中间表数据的矫正的工作十分恼火。因现场采集设备和计量设备运行情况及变更情况不可控。常常造成因非程序因素(自定义名词,大概的意思就是因为现场采集设备断电、计量设备更换、系统基础通讯信息发生变更等一系列认为原因影响数据存储的准确性),影响后期的数据统计分析的准确性和有效性。不时被客户发现直接向市场部投诉说系统不稳定,要求现场排查问题。我擦!牢骚终止。
终究其问题主要是在生成中间表时,没有必要的验证。只是单纯的在某项操作中,添加的生成中间表的响应操作。后期当发现中间表中存在某些影响统计的信息(如按日统计用量,在中间表的却存在夸天的信息描述)。为了完善该内容,曾经尝试创建定时作业,对于中间表进行扫描,将影响统计分析的信息进行自动处理。问题数据还是会有一段时间存储在数据表中,总觉得存在一定的隐患。所以就像开篇的标题,对于生成中间表中数据有效性、规范性,在牺牲更新效率的前提下创建触发器,当计量数据表发生更新操作后,通过触发器自动向中间表进行操作。
create trigger trigger_name on {table_name | view_name} -- 触发器操作对象 可以是数据表 或视图 {for After | Instead of } -- 触发器类型 [ insert, update,delete ] -- 什么情况激活触发器 as sql_statement -- 触发器操作
这里重点强调一下触发器类型,主要分为两种After和Instead of。after 只能绑定到数据表,是在插入、更新、删除操作发生后,激活该触发器。Instead of 从英文直译过来是替代,理解上就是在进行插入、更新、删除发生前,激活该触发器。其能绑定到数据表或者视图。
来一个实例看一下:这里为after类型的触发器,当绑定数据表发生更新操作时触发。触发结果为向中间表添加信息。并加载了数据规范验证。
-----创建MeterReadingData 的T_HouseRealtimeD 数据表 Update 触发器 if (object_id(‘tgr_classes_UpdateHouseRealtimeD‘, ‘TR‘) is not null) drop trigger tgr_classes_UpdateHouseRealtimeD go create trigger tgr_classes_UpdateHouseRealtimeD on Db_MeterReadingData.dbo.T_HouseRealtimeD for update as begin set nocount on --创建旧的仪表数据 declare @HRD_MeterNum nvarchar(50), @HDI_StartHeatNum decimal(18,2), @HDI_EndHeatNum decimal(18,2), @HDI_RunTimeInterval int, @HDI_RunTimeIntervalStart int, @HDI_RunTimeIntervalEnd int, @HDI_StartTime datetime, @HDI_EndTime datetime, @HDI_AvgEntryTemp decimal(18,2), @HDI_AvgEntryTempStart decimal(18,2), @HDI_AvgEntryTempEnd decimal(18,2), @HDI_AvgExportTemp decimal(18,2), @HDI_AvgExportTempStart decimal(18,2), @HDI_AvgExportTempEnd decimal(18,2), @HDI_FluxUsed decimal(18,2), @HDI_FluxUsedStart decimal(18,2), @HDI_FluxUsedend decimal(18,2) --select -- HRD_MeterNum, -- hrd_cumHeat, -- hrd_runtime, -- hrd_collecttime, -- hrd_EntryTemp, -- hrd_ExportTemp, -- hrd_cumFlux --from -- deleted --select -- hrd_cumHeat, -- hrd_runtime, -- hrd_EntryTemp, -- hrd_ExportTemp, -- hrd_cumFlux, -- hrd_collecttime --from -- inserted insert into Db_MeterReadingData.dbo.T_MeterUseHeatingDetailInformation ( HRD_ID, HRD_MeterNum, HDI_StartHeatNum, HDI_EndHeatNum, HDI_RunTimeInterval, HDI_StartTime, HDI_EndTime, HDI_AvgEntryTemp, HDI_AvgExportTemp, HDI_FluxUsed, HDI_isSettlement ) select 0, inserted.HRD_MeterNum, deleted.hrd_cumHeat, inserted.hrd_cumHeat, (inserted.hrd_runtime-deleted.hrd_runtime), deleted.hrd_collecttime, inserted.hrd_collecttime, (inserted.hrd_EntryTemp+deleted.hrd_EntryTemp)/case when datediff(hour,deleted.hrd_collecttime, inserted.hrd_collecttime)>0 then datediff(hour,deleted.hrd_collecttime, inserted.hrd_collecttime) else 1 end, (inserted.hrd_ExportTemp+deleted.hrd_ExportTemp)/case when datediff(hour,deleted.hrd_collecttime, inserted.hrd_collecttime)>0 then datediff(hour,deleted.hrd_collecttime, inserted.hrd_collecttime) else 1 end, (inserted.hrd_cumFlux-deleted.hrd_cumFlux), 0 from deleted inner join inserted on deleted.HRD_MeterNum=inserted.HRD_MeterNum where datediff(hour,deleted.hrd_collecttime,inserted.hrd_collecttime)<=1 if exists(select 1 from deleted inner join inserted on deleted.HRD_MeterNum=inserted.HRD_MeterNum where datediff(hour,deleted.hrd_collecttime,inserted.hrd_collecttime)>1) begin declare @StartTime datetime,@EndTime datetime declare @MeterTableID table ( --HDI_ID int, MeterID nvarchar(50), StartHeatNum decimal(18,2), EndHeatNum decimal(18,2), runTime int, avgEntryTemp decimal(18,2), avgExportTemp decimal(18,2), fluxUsed decimal(18,2), startTime datetime, endTime datetime ) ---init parameter --select @StartTime=‘2014-02-06 19:00:00‘,@EndTime=‘2014-02-08 16:00:00‘ insert into @MeterTableID select inserted.HRD_MeterNum, deleted.hrd_cumHeat, inserted.hrd_cumHeat, (inserted.hrd_runtime-deleted.hrd_runtime), (inserted.hrd_EntryTemp+deleted.hrd_EntryTemp)/case when datediff(hour,deleted.hrd_collecttime, inserted.hrd_collecttime)>0 then datediff(hour,deleted.hrd_collecttime, inserted.hrd_collecttime) else 1 end, (inserted.hrd_ExportTemp+deleted.hrd_ExportTemp)/case when datediff(hour,deleted.hrd_collecttime, inserted.hrd_collecttime)>0 then datediff(hour,deleted.hrd_collecttime, inserted.hrd_collecttime) else 1 end, (inserted.hrd_cumFlux-deleted.hrd_cumFlux), deleted.hrd_collecttime, inserted.hrd_collecttime from deleted inner join inserted on deleted.HRD_MeterNum=inserted.HRD_MeterNum where datediff(hour,deleted.hrd_collecttime,inserted.hrd_collecttime)<=1 --select M_ID from Db_MeterReadingSys.dbo.T_MeterInformation ---init End declare @Count int,@Count_Temp int declare Temp_Main cursor for select MeterID , StartHeatNum, EndHeatNum , runTime, avgEntryTemp , avgExportTemp , fluxUsed , startTime, endTime from @MeterTableID declare @MeterID nvarchar(50), @StartHeatNum decimal(18,2), @EndHeatNum decimal(18,2), @RunTime int, @avgEntryTemp decimal(18,2), @avgExportTemp decimal(18,2), @fluxUsed decimal(18,2) open Temp_Main fetch next from Temp_Main into @MeterID , @StartHeatNum, @EndHeatNum , @RunTime, @avgEntryTemp , @avgExportTemp , @fluxUsed, @StartTime, @EndTime while @@FETCH_STATUS=0 begin set @Count_Temp=0 set @Count=DATEDIFF(HOUR,@StartTime,@EndTime) while @Count_Temp<@Count begin insert into db_meterReadingData.dbo.T_MeterUseHeatingDetailInformation ( HRD_ID, HRD_MeterNum, HDI_StartHeatNum, HDI_EndHeatNum, HDI_RunTimeInterval, HDI_StartTime, HDI_EndTime, HDI_AvgEntryTemp, HDI_AvgExportTemp, HDI_FluxUsed, HDI_isSettlement ) select 0,@MeterID,@StartHeatNum+convert(decimal(18,2),(@Count_Temp*(@EndHeatNum-@StartHeatNum)/@Count)),convert(decimal(18,2),@StartHeatNum+((@Count_Temp+1)*(@EndHeatNum-@StartHeatNum)/@Count)),0,DATEADD(HOUR,@Count_Temp,@StartTime),DATEADD(HOUR,@Count_Temp+1,@StartTime),@avgEntryTemp,@avgExportTemp,convert(decimal(18,2),@fluxUsed/@Count),1 set @Count_Temp= @Count_Temp+1 end fetch next from Temp_Main into @MeterID , @StartHeatNum, @EndHeatNum , @RunTime, @avgEntryTemp , @avgExportTemp , @fluxUsed, @StartTime, @EndTime end close Temp_Main deallocate Temp_Main end end set nocount off go
补充一下在代码中deleted数据表和inserted 数据表,为系统提供的操作虚拟表,下面简单姐晒一下什么情况下待操作税局存储在哪张数据表中。
Insert 操作 inserted 数据表;
delete 操作 delete 数据表;
update 操作 Inserted 数据表和 delerte数据表。
这里还要注意一些细节:
(1)、DELETE 触发器不能捕获 TRUNCATE TABLE 语句。
(2)、触发器中不允许以下 Transact-SQL 语句:
ALTER DATABASE CREATE DATABASE DISK INIT
DISK RESIZE DROP DATABASE LOAD DATABASE
LOAD LOG RECONFIGURE RESTORE DATABASE
RESTORE LOG
代码中的触发器正在测试中,测试样本10W希望等达到预期。也希望以上内容能够帮助到你。
本文出自 “洛山红茶的成长” 博客,请务必保留此出处http://85608547.blog.51cto.com/2093443/1532281