用户系统迁移,同事经验不足,作了数次imp,导致数据库中没有主键的表的数据重复多次。
而且系统已经运行一周了,不可能重复导数据库。涉及6个用户,500多个表。
create table test
(a varchar2(10),
b char(10),
c number,
d date
);
create table test_tmp as
select * from test
minus
select '0','0',0,to_date(null) from dual;
truncate table test;
insert into test select * from test_tmp;
commit;
drop table tmp;
注:
minus后面的sql,可以有下面的函数生成。
SQL> selectf_getcolumns('test') from dual;
F_GETCOLUMNS('TEST')
--------------------------------------------------------------------------------
'0','0',0,to_date(null)
CREATE OR REPLACE function f_getcolumns
(sourceIN VARCHAR2)
return VARCHAR2
as
id_var
VARCHAR2(30);
--name_var VARCHAR2(30);
source_cursorINTEGER;
ignore
INTEGER;
ls_tmp
VARCHAR2(4000);
ls_tmp0
VARCHAR2(30);
BEGIN
ls_tmp := '';
source_cursor := dbms_sql.open_cursor;
DBMS_SQL.PARSE(source_cursor,
'SELECT DATA_TYPE FROM user_tab_columns where lower(TABLE_NAME)=lower('||''''|| source||''''||')',
DBMS_SQL.native);
DBMS_SQL.DEFINE_COLUMN(source_cursor,1,id_var,30);
ignore := DBMS_SQL.EXECUTE(source_cursor);
LOOP
IF DBMS_SQL.FETCH_ROWS(source_cursor)>0 THEN
DBMS_SQL.COLUMN_VALUE(source_cursor,1,id_var);
if id_var in ('VARCHAR2','CHAR') then
ls_tmp0:=''''||'0'||'''';
elsif id_var in ('NUMBER') then
ls_tmp0:='0';
elsif id_var = ('DATE') then
ls_tmp0:='to_date(null)';
end if;
ls_tmp := ls_tmp||ls_tmp0||',';
ELSE
EXIT;
END IF;
END LOOP;
DBMS_SQL.CLOSE_CURSOR(source_cursor);
return substr(ls_tmp,1,length(ls_tmp) - 1);
EXCEPTION
WHEN OTHERS THEN
IF DBMS_SQL.IS_OPEN(source_cursor) THEN
DBMS_SQL.CLOSE_CURSOR(source_cursor);
return 'hello';
END IF;
RAISE;
END;
/
:该函数可能要根据实际情况稍加改动
:对于含有long,long raw,lob等类型的表,需要特殊处理,也很简单。
|