sql server事务回滚(SQL Server 添加Delete操作回滚日志方式)
类别:数据库 浏览量:2697
时间:2021-10-14 00:20:55 sql server事务回滚
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 操作也同样需要这样的回滚日志。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持开心学习网。如有错误或未考虑完全的地方,望不吝赐教。
您可能感兴趣
- navicat如何连接sql数据库(Navicat 连接SQLServer数据库图文步骤)
- sqlserver查看某个库所有表(SQL Server怎么找出一个表包含的页信息Page)
- sqlserver函数条件判断(Sql Server 开窗函数Over的使用实例详解)
- sqlserver数据库文件包括(详解SQL Server数据库状态和文件状态)
- sqlserver数据库备份还原(sqlserver数据库高版本备份还原为低版本的方法)
- sqlserver中的存盘按钮在哪(SQL Server 2016里的sys.dm_exec_input_buffer的问题)
- sqlserver如何可视化表(sql server使用公用表表达式CTE通过递归方式编写通用函数自动生成连续数字和日)
- sql server新建用户无法登录(sqlserver 因为选定的用户拥有对象,所以无法除去该用户的解决方法)
- sqlserver怎么显示变量所占字节数(SQL Server中关于基数估计计算预估行数的一些方法探讨)
- sqlserver2000显示无服务器(SQL SERVER 2000 9003错误的解决方法只适用于SQL2000)
- sqlserver数据库中锁的4种类型(SQLSERVER对加密的存储过程、视图、触发器进行解密推荐)
- 启动sqlserver代理服务失败(SQL Server代理服务无法启动怎么办)
- SqlServer类似正则表达式的字符处理问题(SqlServer类似正则表达式的字符处理问题)
- 怎么写存储过程sql server(SqlServer存储过程实现及拼接sql的注意点)
- SQLServer获取临时表所有列名或是否存在指定列名的方法(SQLServer获取临时表所有列名或是否存在指定列名的方法)
- sqlserver 插入数据的触发器(SQL server 表数据改变触发发送邮件的方法)
- 三千年第一美女鞠婧祎出演白素贞pk杨紫,颜值胜赵雅芝王祖贤(三千年第一美女鞠婧祎出演白素贞pk杨紫)
- 成都轨道交通13号线一期工程最新进展(成都轨道交通13号线一期工程最新进展)
- 越南没事(越南没事情做)
- 重庆旅游攻略(重庆旅游3-4天攻略最佳线路)
- 周杰伦演唱会门票(周杰伦演唱会门票多少钱一张2023)
- 焕然一新 成都轨道集团官方网站改版上线(成都轨道集团官方网站改版上线)
热门推荐
- laravel怎么同时连接数据库(Laravel框架实现多个视图共享相同数据的方法详解)
- js运算符使用教程(js中不常见的运算符与操作符总结)
- react动态添加组件属性(react使用antd的上传组件实现文件表单一起提交功能完整代码)
- C#排序算法的比较
- rabbitmq客户端内存占用(mysql-canal-rabbitmq 安装部署超详细教程)
- python里面的time如何用(详解python:time模块用法)
- django session验证(Django框架验证码用法实例分析)
- python面向对象实例教程(Python面向对象程序设计类的多态用法详解)
- dede织梦怎么在文章下面添加图片(dedecms织梦模板用array调用多个自定义字段并判断的方法)
- sql server修改表的字段类型后,不能保存
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9