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 操作也同樣需要這樣的回滾日誌。
今天就到這裏結束了,下一篇我會介紹關於UPDATE的回滾日誌的建立。Bye Bye~~~














發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章