SQL Server 添加Delete操作回滾日志方式
我們在操作表的時候難免會遇到誤刪除,或者刪掉的數(shù)據(jù)還想恢復(fù)的情況。
也許細(xì)心的朋友會用begin tran rollback/commit 這種事務(wù)來避免出現(xiàn)失誤,但這并不是最保險的。
如果提交了事物發(fā)現(xiàn)刪錯了或者忘記提交從而導(dǎo)致表被鎖,這些問題總是不可避免的。
廢話不多說了,下面直接進(jìn)入正題,通過觸發(fā)器記錄刪除日志,避免誤刪除帶來的尷尬。
下面這段sql粘過去直接運(yùn)行,建立一個存儲過程:
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 觸發(fā)器========================= 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() --==============================將刪掉的數(shù)據(jù)插入備份表============================ 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
接著我們新建一張測試表,并且隨便往表中插入兩組數(shù)據(jù):
Create table test ( id int, name varchar(10), msg varchar(10) ) Insert into test Select 1,'aa','hahah' Union all Select 2,'bb','heihei'
下面執(zhí)行這個SP,在給test表添加回滾日志:
EXEC SP_DELETE_LOG 'test'
細(xì)心的你不難發(fā)現(xiàn),這時候數(shù)據(jù)庫里面應(yīng)該會多出兩張表:
然后我們刪掉一條數(shù)據(jù):
DELETE FROM test WHERE id=1
再查看那兩張表:
沒錯,這時候日志表里有數(shù)據(jù)了,然后我們把 UPDATE_LOG 表中的 RollBackSQ L這一列對應(yīng)的值copy出來執(zhí)行一下:
INSERT INTO test SELECT [id],[name],[msg] FROM BACKUP_test WHERE UPDATEGUID='B0CBBC4F-3432-4D4F-9E17-F17209BF6745'
別copy我上面這段sql,因?yàn)镚UID肯定是不一樣的!
然而,數(shù)據(jù)恢復(fù)了:
最后,delete日志的介紹就結(jié)束了,唯一的不滿足的是只能作用在Delete 操作,其實(shí)UPDATE 操作也同樣需要這樣的回滾日志。
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
在SQL Server中使用SQL語句查詢一個存儲過程被其它所有的存儲過程引用的存儲過程名
在項(xiàng)目開發(fā)中如果有時修改了一個存儲過程,但是如何能夠快速的查找到使用了這個存儲過程的其它存儲過程呢2012-06-06SQL Server數(shù)據(jù)庫中的存儲過程介紹
這篇文章主要介紹了SQL Server數(shù)據(jù)庫中的存儲過程介紹,本文講解了什么是存儲過程、存儲過程語法、存儲過程的一些使用實(shí)例等內(nèi)容,需要的朋友可以參考下2015-01-01解決sql server 數(shù)據(jù)庫,sa用戶被鎖定的問題
這篇文章主要介紹了解決sql server 數(shù)據(jù)庫,sa用戶被鎖定的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06Linux環(huán)境中使用BIEE 連接SQLServer業(yè)務(wù)數(shù)據(jù)源
biee11g默認(rèn)安裝了mssqlserver的數(shù)據(jù)驅(qū)動,不需要在服務(wù)器端進(jìn)行重新安裝,配置過程主要基于ODBC實(shí)現(xiàn),本文主要介紹客戶端為windows、服務(wù)端為linux系統(tǒng)的配置過程。2014-07-07Sql?server連接Oracle數(shù)據(jù)庫完整圖文教程
又一次在項(xiàng)目中用到了在SQLServer添加Oracle鏈接服務(wù)器,索性這里總結(jié)下,這篇文章主要給大家介紹了關(guān)于Sql?server連接Oracle數(shù)據(jù)庫的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01SQL?Server數(shù)據(jù)庫死鎖的原因及處理方法
SQL Server數(shù)據(jù)庫死鎖是指兩個或多個事務(wù)相互等待對方持有的資源,從而導(dǎo)致它們都無法繼續(xù)執(zhí)行的情況,下面這篇文章主要給大家介紹了關(guān)于SQL?Server數(shù)據(jù)庫死鎖的原因及處理方法,需要的朋友可以參考下2024-08-08