工作是数据抽取,分主表和从表,是这样实现的,先从主表查询,然后游标循环
根据主表 主键,再去查从表,然后插入 主表,从表。
主表有1百多W数据量。
代码如下:create or replace procedure proc_test as
cursor c is
select t1.*
from PERSON_INFO@viewOld t1 ;
p PERSON_INFO@viewOld%ROWTYPE;
pid number;
tezheng PERSON_BODYSURCHARACT@viewOld%ROWTYPE;
rhyz PERSON_NORESIDENCE_HOLDER@viewOld%ROWTYPE;
rhyz_isdelete char(1);--
zk_sc char(2);--
zk_flag char(1);--
sc_flag char(1);--
zk_sc_num number;
tezheng_num number;
rhyz_num number;
begin
FOR p IN c LOOP
select SEQ_TB_RY.Nextval into pid from dual;
/*
--不知道是这样快 还是下面select count(*)块,我测试好像差不多
begin
select * into tezheng from PERSON_BODYSURCHARACT@viewOld where V_PERSON_ID =p.v_person_id and rownum<2 ; --
exception
when no_data_found then
null;
end; */
select count(V_PERSON_ID) into tezheng_num from PERSON_BODYSURCHARACT@viewOld where V_PERSON_ID =p.v_person_id ;
if tezheng_num >0 then
select * into tezheng from PERSON_BODYSURCHARACT@viewOld where V_PERSON_ID =p.v_person_id and rownum<2 ; --
end if;
select count(V_PERSON_ID) into rhyz_num from PERSON_NORESIDENCE_HOLDER@viewOld where V_PERSON_ID =p.v_person_id;
if rhyz_num >0 then
select * into rhyz from PERSON_NORESIDENCE_HOLDER@viewOld where V_PERSON_ID =p.v_person_id and rownum<2 ; --
end if;
zk_sc:='0';
select count(l.v_person_no) into zk_sc_num from person_workobject3@viewOld c,PERSON_WORKOBJECT_LG@viewOld l
where p.v_person_id=c.v_person_id and c.v_person_no=l.v_person_no and l.C_CADMIN_REASON is null;
if zk_sc_num >0 then
select nvl(l.C_LADMIN_ZK,'0') into zk_sc from person_workobject3@viewOld c,PERSON_WORKOBJECT_LG@viewOld l
where p.v_person_id=c.v_person_id and c.v_person_no=l.v_person_no and l.C_CADMIN_REASON is null and rownum<2 ;--
end if;
--
rhyz_isdelete:=nvl( rhyz.C_UP,'0');
if rhyz_isdelete='1' then rhyz_isdelete:='0';
end if;
if rhyz_isdelete='0' then rhyz_isdelete:='1';
end if;
zk_flag:='0';sc_flag:='0';
if zk_sc='7' then zk_flag:='1';end if;
if zk_sc='71' then sc_flag:='1';end if;
--dbms_output.put_line(pid);
insert into tb_ry (pid,SFZHM,XM,XB,CSRQ,JG,ZY,WHCD,MZ,HYZK,BMCH,ZJXY,ZZMM,LXSJ,GZBM,LXFS,FLAG_JSBDS,FLAG_SHGJZMRS,JKZK,ZZZHM,HJPCS,HJSX,
HJSQ,HJJX,HJXZ,XZPCS,XZSX,XZSQ,XZJX,XZDZ,ZW,FLAG_JWZX,FLAG_LJSWZX,FLAG_JSJZ,FLAG_QBHS,FLAG_GZRY,SFAY,FLAG_FZCSW,FLAG_XFSF,FLAG_DSCC,FLAG_ZDRK,
--
LX,SG,ZCXH,TX,KY,TSTZ1,TSTZ2,TSTZ3,TSTZ4,TSTZ5,
--
DDBDSJ,LKBDSJ,JZBDYY,LKBDYY,FWXZ,YWWFFZQK,RHYZ,RHYZSJ,FLLX,RYQYLX,ZX,FWCS
)
values (pid,p.V_CARD_ID,p.V_NAME,p.C_SEX,p.d_birthdate,p.C_NATIVE,p.V_EMPLOYMENT,p.C_CULTURE_DEGR,p.C_NATION,p.C_MARRIAGE_STAT,
p.V_NICKNAME || p.V_EVERNAME,p.C_RELIGION,p.C_POLITY_ISA,p.V_MOBILE,p.V_WORKUNIT,p.V_CONTACT_MODE,p.C_LUNACY,p.C_KNOW_NAME,
p.C_HEALTH,p.V_RESIDENCE_NO,p.C_POLICE_STATION,p.V_CITY,p.C_COMMITTEE,p.C_STREET,p.V_DETAIL_ADDRESS,p.C_POLICESTATION_CUR,p.V_CITY_CUR
,p.C_COMMITTEE_CUR,p.C_STREET_CUR,p.V_DETAIL_ADDRESS_CUR,p.N_WORK_POS,p.C_CALLMON_FLAG,p.C_STAYMON_FLAG,p.C_MONIOTR_FLAG,p.c_Waitadmin_Flag
,p.C_ARREST_FLAG,p.C_TRAN_MARK,p.C_ABNORMAL_DIE,p.C_VISIT_MARK,sc_flag,zk_flag
--
,tezheng.V_FACE_SHAPE,tezheng.N_STATURE,tezheng.N_SHOES_CODE,tezheng.V_BODY_SHAPE,tezheng.V_ACCENT,tezheng.V_CHARA1,tezheng.V_CHARA2,
tezheng.V_CHARA3,tezheng.V_CHARA4,tezheng.V_CHARA5
--
,rhyz.D_COME_DATE,rhyz.D_LEAVE_DATE,rhyz.V_LEAVE_REASON,rhyz.V_COME_REASON,rhyz.V_HOUSE_TYPE,rhyz.N_IS_CRIMED,rhyz.V_GATHER_PERSON,
rhyz.D_RECORD_TIME,rhyz.V_APART_TYPE,rhyz.V_AREA_TYPE,rhyz_isdelete,rhyz.V_SERVICE_AREA
);
--从表1
declare cursor help is
select *
from PERSON_HELP@viewOld where V_PERSON_ID =p.v_person_id ;
h PERSON_HELP@viewOld%ROWTYPE;
begin
FOR h IN help LOOP
insert into TB_RY_BJ (PID,ID,SFZH,XM,XB,DW,ZZ,LXDH,ZBH)
values(SEQ_TB_RY_BJ.NEXTVAL,pid,nvl(h.V_IMPORTANT_CARDNO,''),nvl(h.V_HELP_NAME,''),nvl(h.C_HELP_SEX,''),nvl(h.V_HELP_UNIT,'')
,nvl(h.V_ADDRESS,''),nvl(h.V_HELP_PHONE,'') ,0);
commit;
end loop;
end;
--从表2,3,4,5,6,7
一次类推。。都是这样的形式。
commit;
end loop;
end;
根据主表 主键,再去查从表,然后插入 主表,从表。
主表有1百多W数据量。
代码如下:create or replace procedure proc_test as
cursor c is
select t1.*
from PERSON_INFO@viewOld t1 ;
p PERSON_INFO@viewOld%ROWTYPE;
pid number;
tezheng PERSON_BODYSURCHARACT@viewOld%ROWTYPE;
rhyz PERSON_NORESIDENCE_HOLDER@viewOld%ROWTYPE;
rhyz_isdelete char(1);--
zk_sc char(2);--
zk_flag char(1);--
sc_flag char(1);--
zk_sc_num number;
tezheng_num number;
rhyz_num number;
begin
FOR p IN c LOOP
select SEQ_TB_RY.Nextval into pid from dual;
/*
--不知道是这样快 还是下面select count(*)块,我测试好像差不多
begin
select * into tezheng from PERSON_BODYSURCHARACT@viewOld where V_PERSON_ID =p.v_person_id and rownum<2 ; --
exception
when no_data_found then
null;
end; */
select count(V_PERSON_ID) into tezheng_num from PERSON_BODYSURCHARACT@viewOld where V_PERSON_ID =p.v_person_id ;
if tezheng_num >0 then
select * into tezheng from PERSON_BODYSURCHARACT@viewOld where V_PERSON_ID =p.v_person_id and rownum<2 ; --
end if;
select count(V_PERSON_ID) into rhyz_num from PERSON_NORESIDENCE_HOLDER@viewOld where V_PERSON_ID =p.v_person_id;
if rhyz_num >0 then
select * into rhyz from PERSON_NORESIDENCE_HOLDER@viewOld where V_PERSON_ID =p.v_person_id and rownum<2 ; --
end if;
zk_sc:='0';
select count(l.v_person_no) into zk_sc_num from person_workobject3@viewOld c,PERSON_WORKOBJECT_LG@viewOld l
where p.v_person_id=c.v_person_id and c.v_person_no=l.v_person_no and l.C_CADMIN_REASON is null;
if zk_sc_num >0 then
select nvl(l.C_LADMIN_ZK,'0') into zk_sc from person_workobject3@viewOld c,PERSON_WORKOBJECT_LG@viewOld l
where p.v_person_id=c.v_person_id and c.v_person_no=l.v_person_no and l.C_CADMIN_REASON is null and rownum<2 ;--
end if;
--
rhyz_isdelete:=nvl( rhyz.C_UP,'0');
if rhyz_isdelete='1' then rhyz_isdelete:='0';
end if;
if rhyz_isdelete='0' then rhyz_isdelete:='1';
end if;
zk_flag:='0';sc_flag:='0';
if zk_sc='7' then zk_flag:='1';end if;
if zk_sc='71' then sc_flag:='1';end if;
--dbms_output.put_line(pid);
insert into tb_ry (pid,SFZHM,XM,XB,CSRQ,JG,ZY,WHCD,MZ,HYZK,BMCH,ZJXY,ZZMM,LXSJ,GZBM,LXFS,FLAG_JSBDS,FLAG_SHGJZMRS,JKZK,ZZZHM,HJPCS,HJSX,
HJSQ,HJJX,HJXZ,XZPCS,XZSX,XZSQ,XZJX,XZDZ,ZW,FLAG_JWZX,FLAG_LJSWZX,FLAG_JSJZ,FLAG_QBHS,FLAG_GZRY,SFAY,FLAG_FZCSW,FLAG_XFSF,FLAG_DSCC,FLAG_ZDRK,
--
LX,SG,ZCXH,TX,KY,TSTZ1,TSTZ2,TSTZ3,TSTZ4,TSTZ5,
--
DDBDSJ,LKBDSJ,JZBDYY,LKBDYY,FWXZ,YWWFFZQK,RHYZ,RHYZSJ,FLLX,RYQYLX,ZX,FWCS
)
values (pid,p.V_CARD_ID,p.V_NAME,p.C_SEX,p.d_birthdate,p.C_NATIVE,p.V_EMPLOYMENT,p.C_CULTURE_DEGR,p.C_NATION,p.C_MARRIAGE_STAT,
p.V_NICKNAME || p.V_EVERNAME,p.C_RELIGION,p.C_POLITY_ISA,p.V_MOBILE,p.V_WORKUNIT,p.V_CONTACT_MODE,p.C_LUNACY,p.C_KNOW_NAME,
p.C_HEALTH,p.V_RESIDENCE_NO,p.C_POLICE_STATION,p.V_CITY,p.C_COMMITTEE,p.C_STREET,p.V_DETAIL_ADDRESS,p.C_POLICESTATION_CUR,p.V_CITY_CUR
,p.C_COMMITTEE_CUR,p.C_STREET_CUR,p.V_DETAIL_ADDRESS_CUR,p.N_WORK_POS,p.C_CALLMON_FLAG,p.C_STAYMON_FLAG,p.C_MONIOTR_FLAG,p.c_Waitadmin_Flag
,p.C_ARREST_FLAG,p.C_TRAN_MARK,p.C_ABNORMAL_DIE,p.C_VISIT_MARK,sc_flag,zk_flag
--
,tezheng.V_FACE_SHAPE,tezheng.N_STATURE,tezheng.N_SHOES_CODE,tezheng.V_BODY_SHAPE,tezheng.V_ACCENT,tezheng.V_CHARA1,tezheng.V_CHARA2,
tezheng.V_CHARA3,tezheng.V_CHARA4,tezheng.V_CHARA5
--
,rhyz.D_COME_DATE,rhyz.D_LEAVE_DATE,rhyz.V_LEAVE_REASON,rhyz.V_COME_REASON,rhyz.V_HOUSE_TYPE,rhyz.N_IS_CRIMED,rhyz.V_GATHER_PERSON,
rhyz.D_RECORD_TIME,rhyz.V_APART_TYPE,rhyz.V_AREA_TYPE,rhyz_isdelete,rhyz.V_SERVICE_AREA
);
--从表1
declare cursor help is
select *
from PERSON_HELP@viewOld where V_PERSON_ID =p.v_person_id ;
h PERSON_HELP@viewOld%ROWTYPE;
begin
FOR h IN help LOOP
insert into TB_RY_BJ (PID,ID,SFZH,XM,XB,DW,ZZ,LXDH,ZBH)
values(SEQ_TB_RY_BJ.NEXTVAL,pid,nvl(h.V_IMPORTANT_CARDNO,''),nvl(h.V_HELP_NAME,''),nvl(h.C_HELP_SEX,''),nvl(h.V_HELP_UNIT,'')
,nvl(h.V_ADDRESS,''),nvl(h.V_HELP_PHONE,'') ,0);
commit;
end loop;
end;
--从表2,3,4,5,6,7
一次类推。。都是这样的形式。
commit;
end loop;
end;
这样个人感觉比较适中
HJSQ,HJJX,HJXZ,XZPCS,XZSX,XZSQ,XZJX,XZDZ,ZW,FLAG_JWZX,FLAG_LJSWZX,FLAG_JSJZ,FLAG_QBHS,FLAG_GZRY,SFAY,FLAG_FZCSW,FLAG_XFSF,FLAG_DSCC,FLAG_ZDRK,
--
LX,SG,ZCXH,TX,KY,TSTZ1,TSTZ2,TSTZ3,TSTZ4,TSTZ5,
--
DDBDSJ,LKBDSJ,JZBDYY,LKBDYY,FWXZ,YWWFFZQK,RHYZ,RHYZSJ,FLLX,RYQYLX,ZX,FWCS
)
values (pid,p.V_CARD_ID,p.V_NAME,p.C_SEX,p.d_birthdate,p.C_NATIVE,p.V_EMPLOYMENT,p.C_CULTURE_DEGR,p.C_NATION,p.C_MARRIAGE_STAT,
p.V_NICKNAME || p.V_EVERNAME,p.C_RELIGION,p.C_POLITY_ISA,p.V_MOBILE,p.V_WORKUNIT,p.V_CONTACT_MODE,p.C_LUNACY,p.C_KNOW_NAME,
p.C_HEALTH,p.V_RESIDENCE_NO,p.C_POLICE_STATION,p.V_CITY,p.C_COMMITTEE,p.C_STREET,p.V_DETAIL_ADDRESS,p.C_POLICESTATION_CUR,p.V_CITY_CUR
,p.C_COMMITTEE_CUR,p.C_STREET_CUR,p.V_DETAIL_ADDRESS_CUR,p.N_WORK_POS,p.C_CALLMON_FLAG,p.C_STAYMON_FLAG,p.C_MONIOTR_FLAG,p.c_Waitadmin_Flag
,p.C_ARREST_FLAG,p.C_TRAN_MARK,p.C_ABNORMAL_DIE,p.C_VISIT_MARK,sc_flag,zk_flag
--
,tezheng.V_FACE_SHAPE,tezheng.N_STATURE,tezheng.N_SHOES_CODE,tezheng.V_BODY_SHAPE,tezheng.V_ACCENT,tezheng.V_CHARA1,tezheng.V_CHARA2,
tezheng.V_CHARA3,tezheng.V_CHARA4,tezheng.V_CHARA5
--
,rhyz.D_COME_DATE,rhyz.D_LEAVE_DATE,rhyz.V_LEAVE_REASON,rhyz.V_COME_REASON,rhyz.V_HOUSE_TYPE,rhyz.N_IS_CRIMED,rhyz.V_GATHER_PERSON,
rhyz.D_RECORD_TIME,rhyz.V_APART_TYPE,rhyz.V_AREA_TYPE,rhyz_isdelete,rhyz.V_SERVICE_AREA
); 上面的插入命令,可以改善。构造数组,每100笔或者更多,插入一次,可以改善IO.
DECLARE
TYPE DeptRecTab IS TABLE OF dept%ROWTYPE index by binary_integer;
dept_recs DeptRecTab;
CURSOR c1 IS
SELECT deptno, dname, loc FROM dept WHERE deptno > 10;
BEGIN
OPEN c1;
FETCH c1 BULK COLLECT INTO dept_recs;
END; 上面是一个游标直接写入表变量的例子,也可是单独操作属性变量。
例如:
DEPT_RECS[1].DEPT_NO :='A001';
DEPT_RECS[2].DNAME :='HR';
构造内存表变量后,采用FORALL批量绑定的方式,一次性插入数据表。可以改善性能。
下面是一个完整的对比例子。希望能够有参考的意义。
SQL> CREATE OR REPLACE PROCEDURE bulktest
2 IS
3 TYPE numtab IS TABLE OF NUMBER (20)
4 INDEX BY BINARY_INTEGER;
5
6 TYPE nametab IS TABLE OF VARCHAR2 (50)
7 INDEX BY BINARY_INTEGER;
8
9 pnums numtab;
10 pnames nametab;
11 t1 NUMBER;
12 t2 NUMBER;
13 t3 NUMBER;
14 BEGIN
15 FOR j IN 1 .. 1000000
16 LOOP
17 pnums (j) := j;
18 pnames (j) := 'Seq No. ' || TO_CHAR (j);
19 END LOOP;
20
21 SELECT DBMS_UTILITY.get_time
22 INTO t1
23 FROM DUAL;
24
25 FOR i IN 1 .. 1000000
26 LOOP
27 INSERT INTO blktest
28 VALUES (pnums (i), pnames (i));
29 END LOOP;
30
31 SELECT DBMS_UTILITY.get_time
32 INTO t2
33 FROM DUAL;
34
35 FORALL i IN 1 .. 1000000
36 INSERT INTO blktest
37 VALUES (pnums (i), pnames (i));
38
39 SELECT DBMS_UTILITY.get_time
40 INTO t3
41 FROM DUAL;
42
43 DBMS_OUTPUT.put_line ('Execution Time (hsecs)');
44 DBMS_OUTPUT.put_line ('---------------------');
45 DBMS_OUTPUT.put_line ('FOR loop: ' || TO_CHAR (t2 - t1));
46 DBMS_OUTPUT.put_line ('FORALL: ' || TO_CHAR (t3 - t2));
47 END;
48 /Procedure created.
也有可能不是慢在insert这里啊,
所以让你使用dbms_profiler来辅助tuning呀.
1.禁用游标,减少sql引擎和PL/sql引擎数据交换
2.oracle 的sql是集合操作语言,进行批操作,但这个批要合适,一般建议为50万到500万,取决于你的整体数据规模
3.for all不是循环,归根揭底还是模拟循环操作,只是一次提交给sql引擎一批sql而已,还是行操作,所以性能肯定不是最优的,但比游标循环要好的多