栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 数据库 > MySQL > MsSql

SQL Server 添加Delete操作回滚日志方式

MsSql 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SQL Server 添加Delete操作回滚日志方式

我们在操作表的时候难免会遇到误删除,或者删掉的数据还想恢复的情况。

也许细心的朋友会用begin tran rollback/commit 这种事务来避免出现失误,但这并不是最保险的。

如果提交了事物发现删错了或者忘记提交从而导致表被锁,这些问题总是不可避免的。

废话不多说了,下面直接进入正题,通过触发器记录删除日志,避免误删除带来的尴尬。

下面这段sql粘过去直接运行,建立一个存储过程:
CREATE PROCEDURE [dbo].[SP_DELETe_LOG]
 @TABLENAME VARCHAr(50)
AS
BEGIN
	SET NOCOUNT ON;
 IF NOT EXISTS(SELECT * FROM sys.tables WHERe NAME = @TABLENAME AND TYPE = 'U' )
	BEGIN
		PRINT'ERROR:not exist table '+@TABLENAME
		RETURN
	END
	IF (@TABLENAME LIKE'BACKUP_%' OR @TABLENAME='UPDATe_LOG' )
	BEGIN
		--PRINT'ERROR:not exist table '+@TABLENAME
		RETURN
	END
	--================================判断是否存在 UPDATE_LOG 表============================
	IF NOT EXISTS(SELECT * FROM sys.tables WHERe NAME = 'UPDATe_LOG' AND TYPE = 'U')
		CREATE TABLE UPDATE_LOG
		(
			UpdateGUID VARCHAr(36),
			UpdateTime DATETIME,
			TableName varchar(20),
			UpdateType varchar(6),
			RollBackSQL varchar(1000)
		)
	--=================================判断是否存在 BACKUP_ 表================================
	IF NOT EXISTS(SELECT * FROM sys.tables WHERe NAME = 'BACKUP_'+@TABLENAME AND TYPE = 'U')
	BEGIN
		--DECLARE @SQL VARCHAr(500)
		--SET @SQL='SELECt TOP 1 NEWID() AS [UpdateGUID],* INTO BACKUP_'+@TABLENAME+' FROM '+ @TABLENAME+'
		--		 DELETe FROM BACKUP_'+@TABLENAME
		--SELECt @SQL
		--EXEC(@SQL)
		DECLARE test_Cursor CURSOR FOR
		SELECT COLUMN_NAME,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.columns 
		WHERe TABLE_NAME=@TABLENAME
		OPEN test_Cursor
		DECLARE @SQLTB NVARCHAr(MAX)=''
		DECLARE @COLUMN_NAME NVARCHAr(50),@DATA_TYPE VARCHAr(20),@CHARACTER_MAXIMUM_LENGTH INT
		FETCH NEXT FROM test_Cursor INTO @COLUMN_NAME,@DATA_TYPE,@CHARACTER_MAXIMUM_LENGTH
		WHILE @@FETCH_STATUS=0
		BEGIN
			SET @SQLTB=@SQLTB+'['+@COLUMN_NAME+'] '+@DATA_TYPE+CASE ISNULL(@CHARACTER_MAXIMUM_LENGTH,0) WHEN 0 THEN '' WHEN -1 THEN '(MAX)' ELSE'('+CAST(@CHARACTER_MAXIMUM_LENGTH AS VARCHAr(10))+')' END+','
			FETCH NEXT FROM test_Cursor INTO @COLUMN_NAME,@DATA_TYPE,@CHARACTER_MAXIMUM_LENGTH
		END
		SET @SQLTB='CREATE TABLE BACKUP_'+@TABLENAME+' (UpdateGUID varchar(36),'+SUBSTRINg(@SQLTB,1,LEN(@SQLTB)-1)+')'
		EXEC (@SQLTB)
		CLOSE test_Cursor 
		DEALLOCATE test_Cursor
	END
	--======================================判断是否存在 DELETE 触发器=========================
	IF NOT EXISTS(SELECT * FROM sys.objects WHERe NAME = 'tg_'+@TABLENAME+'_Delete' AND TYPE = 'TR')
	BEGIN
		DECLARE @SQLTR NVARCHAr(MAX)
		SET @SQLTR='
			CREATE TRIGGER tg_'+@TABLENAME+'_Delete
				ON '+@TABLENAME+'
				AFTER delete
			AS 
			BEGIN	
				SET NOCOUNT ON;
				--==============================获取GUID==========================================
				DECLARE @NEWID VARCHAr(36)=NEWID()
				--==============================将删掉的数据插入备份表============================
				INSERT INTO [dbo].[BACKUP_'+@TABLENAME+']
				SELECT @NEWID,* FROM deleted
				--==============================记录日志和回滚操作的SQL===========================
				--*********************生成列名**********************
				DECLARE @COLUMN NVARCHAr(MAX)=''''
				SELECT @COLUMN+='',[''+COLUMN_NAME+'']'' FROM INFORMATION_SCHEMA.columns
				WHERe TABLE_NAME='''+@TABLENAME+''' 
				AND COLUMNPROPERTY(OBJECT_ID('''+@TABLENAME+'''),COLUMN_NAME,''IsIdentity'')<>1 --非自增字段
				SET @COLUMN=SUBSTRINg(@COLUMN,2,LEN(@COLUMN))
				INSERT INTO [dbo].[UPDATe_LOG]
				SELECT @NEWID,GETDATE(),'''+@TABLENAME+''',''DELETE'',''INSERT INTO '+@TABLENAME+' SELECT ''+@COLUMN+'' FROM BACKUP_'+@TABLENAME+' WHERe UPDATeGUID=''''''+@NEWID+''''''''
			END
			'
		EXEC(@SQLTR)
	END
END

接着我们新建一张测试表,并且随便往表中插入两组数据:

 Create table test 
 (
 id int,
 name varchar(10),
 msg varchar(10)
 )
 Insert into test
 Select 1,'aa','hahah'
 Union all 
 Select 2,'bb','heihei'

下面执行这个SP,在给test表添加回滚日志:

EXEC SP_DELETE_LOG 'test'

细心的你不难发现,这时候数据库里面应该会多出两张表:

然后我们删掉一条数据:

DELETE FROM test WHERe id=1

再查看那两张表:

没错,这时候日志表里有数据了,然后我们把 UPDATe_LOG 表中的 RollBackSQ L这一列对应的值copy出来执行一下:

INSERT INTO test SELECT [id],[name],[msg] FROM BACKUP_test WHERe UPDATEGUID='B0CBBC4F-3432-4D4F-9E17-F17209BF6745'

别copy我上面这段sql,因为GUID肯定是不一样的!

然而,数据恢复了:

最后,delete日志的介绍就结束了,唯一的不满足的是只能作用在Delete 操作,其实UPDATE 操作也同样需要这样的回滚日志。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持考高分网。如有错误或未考虑完全的地方,望不吝赐教。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/168739.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号