首页 > 代码库 > Sql server 2008 触发器实现

Sql server 2008 触发器实现

    昨天在进行系统升级中,对于某些程序生成的中间表数据的矫正的工作十分恼火。因现场采集设备和计量设备运行情况及变更情况不可控。常常造成因非程序因素(自定义名词,大概的意思就是因为现场采集设备断电、计量设备更换、系统基础通讯信息发生变更等一系列认为原因影响数据存储的准确性),影响后期的数据统计分析的准确性和有效性。不时被客户发现直接向市场部投诉说系统不稳定,要求现场排查问题。我擦!牢骚终止。

    终究其问题主要是在生成中间表时,没有必要的验证。只是单纯的在某项操作中,添加的生成中间表的响应操作。后期当发现中间表中存在某些影响统计的信息(如按日统计用量,在中间表的却存在夸天的信息描述)。为了完善该内容,曾经尝试创建定时作业,对于中间表进行扫描,将影响统计分析的信息进行自动处理。问题数据还是会有一段时间存储在数据表中,总觉得存在一定的隐患。所以就像开篇的标题,对于生成中间表中数据有效性、规范性,在牺牲更新效率的前提下创建触发器,当计量数据表发生更新操作后,通过触发器自动向中间表进行操作。

    

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