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

今天接到客户电话,说操作数据无法保存。经过分析,发现他的数据库已经有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'

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

转帖:http://blog.csdn.net/cswangbin/archive/2010/01/26/5258276.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值