下面是我写的一个存储过程,第一次写存储过程,运行速度很慢,哪位高手帮忙给提点意见,这个过程该怎么优化,或者哪里需要优化.谢谢各位了!
CREATE OR REPLACE PROCEDURE test_sjjc(
lctable IN VARCHAR,
lctabzj IN NUMBER ,
lczj IN YWSLLCSLB.ZJ%TYPE
)
IS
str_zj VARCHAR2 (200); --sql语句的主键值变量
str_up VARCHAR2 (2000); --sql语句的临时变量
str_p VARCHAR2 (2000); --sql语句的临时变量
wj VARCHAR2 (200); --sql语句中外键的临时变量
zjm VARCHAR2 (200); --sql语句中的主键名
checkid NUMBER := 0; --判断第一个循环是否执行 TYPE sel IS REF CURSOR; --声明一个游标
sel_zzj sel; --定义一个游标
BEGIN
FOR i_table IN ((SELECT t1.table_name tname
FROM user_constraints t1,user_cons_columns t2
WHERE t1.r_constraint_name = t2.constraint_name
AND t2.table_name = lctable
INTERSECT
SELECT DISTINCT(BYWM) tablename
FROM SJJC_ZDJCTABLE,
(SELECT ywlcdm
FROM YWSSLB
WHERE ZJ = lczj) ywlcdm_t
WHERE LCDM = ywlcdm_t.ywlcdm)
MINUS
SELECT DISTINCT bywm
FROM sjjc_output s
WHERE s.lcslzj = lczj)
LOOP
checkid := checkid + 1; --检索出表的主键
SELECT col.column_name cname
INTO zjm
FROM user_constraints con,
user_cons_columns col
WHERE con.constraint_name = col.constraint_name
AND con.constraint_type = 'P'
AND con.table_name = i_table.tname;
--检索出表的外键名
SELECT r.column_name
INTO wj
FROM user_cons_columns col,
(SELECT coln.table_name, coln.column_name, conn.r_constraint_name
FROM user_constraints conn, user_cons_columns coln
WHERE conn.constraint_name = coln.constraint_name
AND coln.table_name = i_table.tname) r
WHERE r.r_constraint_name = col.constraint_name
AND col.table_name = lctable; str_p :=
' SELECT ' || zjm ||
' FROM ' || i_table.tname ||
' WHERE ' || wj || ' = '|| lctabzj;
str_up :=
str_p ||
' UNION ALL ' ||
' SELECT DISTINCT(0) ' || zjm ||
' FROM dual ' ||
' WHERE NOT EXISTS(' || str_p || ')';
OPEN sel_zzj FOR str_up;
LOOP
--得到和流程相关的表的主键值
FETCH sel_zzj INTO str_zj;
EXIT WHEN sel_zzj%NOTFOUND;
--执行检查模块
TEST_SJJC_GYTDSYQDJ_CRDJ(i_table.tname, str_zj, lczj);
IF str_zj != 0 AND str_zj IS NOT NULL
THEN
test_sjjc(i_table.tname, str_zj,lczj);
END IF;
END LOOP;
CLOSE sel_zzj;
END LOOP;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END test_sjjc
CREATE OR REPLACE PROCEDURE test_sjjc(
lctable IN VARCHAR,
lctabzj IN NUMBER ,
lczj IN YWSLLCSLB.ZJ%TYPE
)
IS
str_zj VARCHAR2 (200); --sql语句的主键值变量
str_up VARCHAR2 (2000); --sql语句的临时变量
str_p VARCHAR2 (2000); --sql语句的临时变量
wj VARCHAR2 (200); --sql语句中外键的临时变量
zjm VARCHAR2 (200); --sql语句中的主键名
checkid NUMBER := 0; --判断第一个循环是否执行 TYPE sel IS REF CURSOR; --声明一个游标
sel_zzj sel; --定义一个游标
BEGIN
FOR i_table IN ((SELECT t1.table_name tname
FROM user_constraints t1,user_cons_columns t2
WHERE t1.r_constraint_name = t2.constraint_name
AND t2.table_name = lctable
INTERSECT
SELECT DISTINCT(BYWM) tablename
FROM SJJC_ZDJCTABLE,
(SELECT ywlcdm
FROM YWSSLB
WHERE ZJ = lczj) ywlcdm_t
WHERE LCDM = ywlcdm_t.ywlcdm)
MINUS
SELECT DISTINCT bywm
FROM sjjc_output s
WHERE s.lcslzj = lczj)
LOOP
checkid := checkid + 1; --检索出表的主键
SELECT col.column_name cname
INTO zjm
FROM user_constraints con,
user_cons_columns col
WHERE con.constraint_name = col.constraint_name
AND con.constraint_type = 'P'
AND con.table_name = i_table.tname;
--检索出表的外键名
SELECT r.column_name
INTO wj
FROM user_cons_columns col,
(SELECT coln.table_name, coln.column_name, conn.r_constraint_name
FROM user_constraints conn, user_cons_columns coln
WHERE conn.constraint_name = coln.constraint_name
AND coln.table_name = i_table.tname) r
WHERE r.r_constraint_name = col.constraint_name
AND col.table_name = lctable; str_p :=
' SELECT ' || zjm ||
' FROM ' || i_table.tname ||
' WHERE ' || wj || ' = '|| lctabzj;
str_up :=
str_p ||
' UNION ALL ' ||
' SELECT DISTINCT(0) ' || zjm ||
' FROM dual ' ||
' WHERE NOT EXISTS(' || str_p || ')';
OPEN sel_zzj FOR str_up;
LOOP
--得到和流程相关的表的主键值
FETCH sel_zzj INTO str_zj;
EXIT WHEN sel_zzj%NOTFOUND;
--执行检查模块
TEST_SJJC_GYTDSYQDJ_CRDJ(i_table.tname, str_zj, lczj);
IF str_zj != 0 AND str_zj IS NOT NULL
THEN
test_sjjc(i_table.tname, str_zj,lczj);
END IF;
END LOOP;
CLOSE sel_zzj;
END LOOP;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END test_sjjc
解决方案 »
- 请教:如何跟踪delphi开发的程序的数据库操作
- 关于oralce case 语句和decode函数的问题
- 获取存储过程的参数列表
- 如何看一个oracle数据库的裸数据大小?
- 求一aix下oracle 10g的自动备份脚本
- toad或pl/sql developer的小问题
- 求大神写个SQL 或者过程
- update table1 set i=i+1 where j in (select id from 游标); 这样不知道可以么,到家帮我看看
- oracal9.0不创建数据库,高手请帮忙
- ORACLE9中没有init.ora文件吗?请用过ORACLE9的大哥帮忙看看~
- 如何修改系统时间
- 请问关于阶段性时间归总的sql语句
Minus,对两个结果集进行差操作,已经不包括重复行,所以不需要加distinct
建议先将数据放到临时表中,然后从临时表中提取进行循环处理,性能会高很多的。
可以采用分析函数来解决内层循环的问题,那样性能会高很多!
还有str_up这个sql,似乎也可以优化,因为后面又是从dual去查not exists的。
还有TEST_SJJC_GYTDSYQDJ_CRDJ(i_table.tname, str_zj, lczj);
IF str_zj != 0 AND str_zj IS NOT NULL
THEN
test_sjjc(i_table.tname, str_zj,lczj);
END IF;
递归调用可能会有问题,比如递归的某一个commit了,外层rollback不回去吧?
主外键的查询确实可以放在一块,但是效率和分开差不多,写一块后要嵌套子查询,比现在的长,可读性就差了;
NOT EXISTS的我再想想,看看如何再优化。
关于递归commit的确实是这样,应该再完善一下。
服务器性能这个我也是这么想的,服务器业务肯定比本地多,只是没想到差这么多。我要完成的功能是给出一个流程表名及主键,在数据库中通过这个表获得和这个流程表相关的所有业务表,并通过TEST_SJJC_GYTDSYQDJ_CRDJ()过程进行处理,这个TEST_SJJC_GYTDSYQDJ_CRDJ 过程效率还行,我现在列出的只是查找从从表关联主表的内容,还有一个和从主表关联从表的过程,很类似,没有列出来。
user_cons_column和 user_constraints 是系统视图,通过这两个视图获得相关表的关系。