English
 电子信箱
 加入收藏

  威盾防火墙 >> 新闻中心 >> 业界动态 >> SQL数据库表坏了的手动恢复方法

 

SQL数据库表坏了的手动恢复方法

威盾防火墙 2014-12-12

 

  今天接到客户电话,说操作数据无法保存。经过分析,发现他的数据库已经有5G多的大小,而最终发现有张表的索引出错了,用DBCC CHECK也无力回天。

每次用select * from ln003082 语句查询,都报如下错误:

服务器: 消息 605,级别 21,状态 1,行 1
试图从数据库 'ln_fl0125' 中提取的逻辑页 (1:629904) 属于对象 '869578136',而非对象 'LN003082'。

连接中断

没办法,只能想办法恢复了。还好有几位老手在身边。于是通如以下步骤勉强恢复有效数据,当然,有部份单子数据是丢失了。只能叫客户再去补了。

 首先要确定哪些数据回不来了,通过游标来一一确定哪些数据无效了。

declare @bill_no varchar(20)
declare @shop_no varchar(20)
DECLARE  @QTY INT

DECLARE terminal_changecursor CURSOR FOR 
   select bill_no,shop_no from terminal_change
   group by shop_no,bill_no
   ORDER by shop_no,bill_no


OPEN terminal_changecursor
FETCH NEXT FROM terminal_changecursor into  @bill_no ,@shop_no
WHILE @@FETCH_STATUS = 0
BEGIN
 FETCH NEXT FROM terminal_changecursor into  @bill_no ,@shop_no

 PRINT  @bill_no +'-'+@shop_no
 IF  NOT ( 
(@bill_no='MB10010033' AND @shop_no = 'P9ZT') OR   
(@bill_no='MT90910001' AND @shop_no = 'P9ZT') OR
(@bill_no='MT00110002' AND @shop_no = 'P10D') OR
(@bill_no='MB10010034' AND @shop_no = 'P9ZT') OR
(@bill_no='MB10010035' AND @shop_no = 'P9ZT')  
 

)
 select @QTY=sum(bill_qty) from LN003082 WHERE   bill_no=@bill_no AND  shop_no=@shop_no
ENDEND

DEALLOCATE terminal_changecursor
GO

通过上面的语句,可以查到哪些单号的数据出了问题。用IF跳过有问题的数据,当select sum通过游标查询时,如果有问题的数据,就会停下来中断,根据print出来的单号,将其加入下次IF中,这个步骤很枯燥。不过一般不会出现过多丢失的数据,也只能这样一一确定了。

接下来就是根据查询出来有问题的数据,进行过滤恢复了。

恢复方法脚本如下:

主要有3步。

--说明:终端变动数据表坏了,丢失五张数据,请通知重传


--1。重建表LN003082为LN003082_new,用于转移有效数据
select * into LN003082_new from LN003082 where 1=2
GO

 CREATE  INDEX [IX_TERMINAL_CHANGE_BILL_NO] ON [dbo].[LN003082_new]([BILL_NO], [SHOP_NO]) ON [PRIMARY]
GO

 CREATE  INDEX [R_TC_GOODS_FK] ON [dbo].[LN003082_new]([GOODS_NO]) ON [PRIMARY]
GO

 CREATE  INDEX [R_TC_SHOP_FK] ON [dbo].[LN003082_new]([SHOP_NO]) ON [PRIMARY]
GO

 CREATE  INDEX [IX_TERMINAL_CHANGE_VALID_DATE] ON [dbo].[LN003082_new]([VALID_DATE]) ON [PRIMARY]
GO

 CREATE  INDEX [IX_TERMINAL_CHANGE] ON [dbo].[LN003082_new]([ACC_VALID_DATE]) ON [PRIMARY]
GO

 CREATE  INDEX [IX_TERMINAL_CHANGE_INTER_BILLNO] ON [dbo].[LN003082_new]([INTER_BILLNO], [SHOP_NO]) ON [PRIMARY]
GO

--2。将有效数据导入LN003082_new

declare @bill_no varchar(20)
declare @shop_no varchar(20)
DECLARE  @QTY INT

DECLARE terminal_changecursor CURSOR FOR 
   select bill_no,shop_no from terminal_change
   group by shop_no,bill_no
   ORDER by shop_no,bill_no


OPEN terminal_changecursor
FETCH NEXT FROM terminal_changecursor into  @bill_no ,@shop_no
WHILE @@FETCH_STATUS = 0
BEGIN
 FETCH NEXT FROM terminal_changecursor into  @bill_no ,@shop_no

 IF  NOT ( 
  (@bill_no='MB10010033' AND @shop_no = 'P9ZT') OR   
  (@bill_no='MT90910001' AND @shop_no = 'P9ZT') OR
  (@bill_no='MT00110002' AND @shop_no = 'P10D') OR
  (@bill_no='MB10010034' AND @shop_no = 'P9ZT') OR
  (@bill_no='MB10010035' AND @shop_no = 'P9ZT') 
  )
  INSERT INTO LN003082_new SELECT * FROM LN003082 WHERE   bill_no=@bill_no AND  shop_no=@shop_no
END

DEALLOCATE terminal_changecursor
GO

--3。将转移好数据的表改名为LN003082 
exec sp_rename  'LN003082','LN003082olderror'
exec sp_rename  'LN003082_new','LN003082'

===================================================


相关内容: 最新内容:
手动sql注入(初级篇)[2014-12-12]
如何防止存储过程拼接字符串的sql注入问题[2014-12-12]
五种提高 SQL 性能的方法[2014-12-12]
Sql Server存储过程编写经验和优化措[2014-12-12]
SQL Server应用程序中的高级SQL注入(2)[2014-12-12]
如何进行防SQL注入?[2014-12-11]
手动sql注入(初级篇)[2014-12-12]
如何防止存储过程拼接字符串的sql注入问题[2014-12-12]
vs2005操作word2003![2014-12-12]
服务器(WIndows2003)部署asp.net网站生成word文档经常遇到的问题![2014-12-12]
NET1.1下,使用C#自动生成Word2003文档(通过操作COM组件实现)[2014-12-12]
Ajax错误处理机制技术探讨[2014-12-12]