用了truncate table 表 .. 把表误删了, 现在用时间戳和scn 都不能恢复,提示表定义更改 , 然后通过重新建立索引,主键什么的, 还是提示表定义更改。 请问还有办法还原数据吗 .
------解决思路----------------------
找以前的备份来恢复吧
------解决思路----------------------
只能找以前的备份恢复了
------解决思路----------------------
翻了翻以前的文档,还真找到一个truncate的恢复文档,参考
/*
truncate表后的数据恢复测试(对于drop purge也可以仿照此方法)
*/
--step1:首次创建测试表并删除
create table trunc_tab(id int,name char(800)) pctfree 99;
begin
for i in 1 .. 10 loop
insert into trunc_tab
values
(i, dbms_random.string('p', 10)
------解决思路----------------------
'中国');
end loop;
commit;
end;
select count(distinct dbms_rowid.rowid_block_number(rowid)) cnt
from trunc_tab;
drop table trunc_tab;
--step2:再次创建测试表
create table trunc_tab(id int,name char(800)) pctfree 99;
begin
for i in 1 .. 100 loop
insert into trunc_tab
values
(i, dbms_random.string('p', 10)
------解决思路----------------------
'中国');
end loop;
commit;
end;
--确定块数
select count(distinct dbms_rowid.rowid_block_number(rowid)) cnt
from trunc_tab;
--step3:创建参照表
create table trunc_tab_ref as select * from trunc_tab;
--step4:truncate待恢复表
truncate table trunc_tab;
--step5:立即关闭数据库,并启动到受限模式
--step6:查看表头
select ds.header_file, ds.header_block
from dba_segments ds
where segment_name = 'TRUNC_TAB'
order by 2;
alter system dump datafile 6 block 1083;
--当然我们从dump出来的块头中是再也看不到
--extent的历史信息,也许你会想到以sys来
--闪回查询dba_extents,但是dba_extents
--查不到这些信息(我也纳闷为什么不可以)
--step7:查看当前区中一个数据块内容
alter system dump datafile 6 block 1086;
--我们要找到是段信息:
seg/obj: 0xba46
--这个信息是关键,truncate表时oracle只是将对应的
--块标记为可用状态,而并不会清空块中实际内容
--step8:按块顺序dump出trunc_tab表所在数据文件所有块内容
--step9:创建外部表以读取dump出的文件内容
create table dump_block_contents
(text varchar2(4000)
)
organization external
(type oracle_loader
default directory DATA_PUMP_DIR
access parameters
(records delimited by newline
fields (text (1:4000) char))
location ('zhangyu_ora_3484.trc'));
--step9:创建临时表(共解析出的二进制字段使用)
create table temp(id number,name clob);
--step10:创建解析文本的存储过程
declare
cursor c_text is
select text from t_alert;
v_text c_text%rowtype;
col_value varchar2(32767);
cnt_flag number := 0;
begin
open c_text;
loop
fetch c_text
into v_text;
exit when c_text%notfound;
if regexp_instr(v_text.text, 'seg[/]obj:[ ]{0,}0xba46') > 0 then
loop
fetch c_text
into v_text;
exit when c_text%notfound;
if regexp_instr(v_text.text, 'col[ ]{1,}[[:digit:]]{1,}[ ]{0,}:') > 0 then
col_value := replace(regexp_replace(v_text.text,
'.+[]][ ]{0,}(.*)$',
'\1'),
' ');
<<next_col>>
begin
null;
end;
loop
fetch c_text
into v_text;
exit when c_text%notfound;
if regexp_instr(v_text.text,
'col[ ]{1,}[[:digit:]]{1,}[ ]{0,}:') = 0 and
v_text.text <> 'end_of_block_dump' then
col_value := col_value
------解决思路----------------------
replace(regexp_replace(v_text.text,
'.+[]][ ]{0,}(.*)$',
'\1'),
' ');
elsif v_text.text = 'end_of_block_dump' then
insert into temp (id, name) values (cnt_flag, col_value);
cnt_flag := cnt_flag + 1;
goto next_block;
elsif regexp_instr(v_text.text,
'col[ ]{1,}[[:digit:]]{1,}[ ]{0,}:') > 0 then
insert into temp (id, name) values (cnt_flag, col_value);
cnt_flag := cnt_flag + 1;
col_value := replace(regexp_replace(v_text.text,
'.+[]][ ]{0,}(.*)$',
'\1'),
' ');
goto next_col;
else
null;
end if;
end loop;
else
null;
end if;
end loop;
else
null;
end if;
<<next_block>>
begin
null;
end;
end loop;
close c_text;
commit;
end;
--step11:根据解析出的二进制字段信息生成insert语句
with t as
(
select wm_concat('q''a'
------解决思路----------------------
col
------解决思路----------------------
'a''') over(partition by group# order by id) col1,
id,
group#,
max(id) over(partition by group#) as mx_id
from (select case
when mod(rownum, 2) = 1 then
to_char(utl_raw.cast_to_number(to_char(name)))
else
utl_raw.cast_to_varchar2(to_char(name))
end as col,
ntile(100) over(order by null) as group#,
rownum id
from (select * from temp order by id))
)
select 'insert into trunc_tab(id,name) values('
------解决思路----------------------
col1
------解决思路----------------------
');'
from t
where id = mx_id;
--step12:在sql*plus中执行生成的insert语句
set define off;
@filename.sql