- 浏览: 27993 次
- 性别:
- 来自: 上海
文章分类
最新评论
http://sosuny.iteye.com/blog/551006
一、Oracle临时表知识
在Oracle中,临时表分为SESSION、TRANSACTION两种,SESSION级的临时表数据在整个SESSION都存在,直到结束此次SESSION;而 TRANSACTION级的临时表数据在TRANACTION结束后消失,即COMMIT/ROLLBACK或结束SESSION都会清除 TRANACTION临时表数据。
1) 会话级临时表 示例
1创建
Sql代码
1.create global temporary table temp_tbl(col_a varchar2(30))
2.on commit preserve rows
create global temporary table temp_tbl(col_a varchar2(30))
on commit preserve rows
2插入数据
Sql代码
1.insert into temp_tbl values('test session table')
insert into temp_tbl values('test session table')
3提交
Sql代码
1.commit;
commit;
4查询
Sql代码
1.select *from temp_tbl
select *from temp_tbl
可以看到数据'test session table'记录还在。
结束SESSION,重新登录,再查询数据select *from temp_tbl,这时候记录已不存在,因为系统在结束SESSION时自动清除记录 。
2) 事务级临时表 示例
1创建
Sql代码
1.create global temporary table temp_tbl(col_a varchar2(30))
2.on commit delete rows
create global temporary table temp_tbl(col_a varchar2(30))
on commit delete rows
2插入数据
Sql代码
1.insert into temp_tbl values('test transaction table')
insert into temp_tbl values('test transaction table')
3提交
Sql代码
1.commit ;
commit ;
4查询
Sql代码
1.select *from temp_tbl
select *from temp_tbl
这时候可以看到刚才插入的记录'test transaction table'已不存在了,因为提交时已经晴空了数据库;同样,如果不提交而直接结束SESSION,重新登录记录也不存在 。
二、在Oracle存储中使用临时表的一个例子
描述:档案册借阅时,需要把册拆分成详细的单据,拆分依据是册表中的BILLCODES(若干个用逗号分割的单据号)字段,临时表用于保存拆分出来的单据信息。拆分结束后直接返回临时表的数据。
Sql代码
1.create or replace package AMS_PKG as
2. type REFCURSORTYPE is REF CURSOR;
3. procedure SPLIT_VOLUMES (P_CORP_NAME IN varchar2,P_YEAR IN varchar2,P_MONTH IN varchar2,P_VOL_TYPE_CODE IN varchar2,P_BILL_NUM IN varchar2,P_VOLUME_NUM IN varchar2,P_AREA_CODES IN varchar2,P_QUERY_SQL out varchar2,P_OUTCURSOR out refCursorType);
4.end AMS_PKG;
5./
6.CREATE OR REPLACE PACKAGE BODY "AMS_PKG" as
7. procedure SPLIT_VOLUMES(p_CORP_NAME IN varchar2, --查询条件,公司名称
8. p_YEAR IN varchar2, --查询条件,会计年度
9. p_MONTH IN varchar2, --查询条件,期间
10. p_VOL_TYPE_CODE IN varchar2, --查询条件,凭证类别编码
11. p_BILL_NUM IN varchar2, --查询条件,信息单号
12. p_VOLUME_NUM IN varchar2, --查询条件,册号
13. p_AREA_CODES IN varchar2, --查询条件,所在区域编码(产生册的区域),逗号分割。
14. --形式如 '12C01','12201','12D01','12E01','12601',存储过程中将使用in的方式进行过滤
15. p_QUERY_SQL out varchar2, --返回查询字符串
16. p_OutCursor out refCursorType --返回值
17. ) is
18.
19. v_sql varchar2(3000);
20. v_sql_WHERE varchar2(3000);
21. v_temp1 varchar2(300);
22. v_temp2 varchar2(300);
23. v_tempBILLCODES varchar2(3000);
24. V_CNT NUMBER(10,0);
25. V_VOLUME_ID NUMBER(10,0);
26. mycur refCursorType;
27. --CURSOR mycur( v varchar2) is
28. -- SELECT VOUCHTYPE,BILLCODES FROM PUB_VOLUMES where volumeid=v;
29. CURSOR mycur_split( val varchar2,splitMark varchar2) is
30. select * from table(myutil_split(val,splitMark));
31. begin
32. v_temp1 :='';
33. v_temp2 :='';
34. v_sql_WHERE := '';
35. v_tempBILLCODES := '';
36. V_CNT := 0;
37. V_VOLUME_ID := 0;--册表的系统编号
38. v_sql := 'SELECT VOLUMEID,VOUCHTYPE,BILLCODES FROM PUB_VOLUMES WHERE 1=1 ';
39. --dbms_output.put_line('p_BILL_NUM='||p_BILL_NUM);
40.
41.
42. IF (p_CORP_NAME IS NOT NULL AND LENGTH(p_CORP_NAME) >0) THEN --公司名称
43. BEGIN
44. v_sql_WHERE := v_sql_WHERE || ' AND CORPNAME LIKE ''%';
45. v_sql_WHERE := v_sql_WHERE || p_CORP_NAME;
46. v_sql_WHERE := v_sql_WHERE || '%''';
47. --dbms_output.put_line(p_BILL_NUM);
48. END;
49. END IF;
50. IF (p_YEAR IS NOT NULL AND LENGTH(p_YEAR) >0) THEN --会计年度
51. BEGIN
52. v_sql_WHERE := v_sql_WHERE || ' AND YEAR = ''';
53. v_sql_WHERE := v_sql_WHERE || p_YEAR;
54. v_sql_WHERE := v_sql_WHERE || '''';
55. --dbms_output.put_line(p_BILL_NUM);
56. END;
57. END IF;
58. IF (p_MONTH IS NOT NULL AND LENGTH(p_MONTH) >0) THEN --期间
59. BEGIN
60. v_sql_WHERE := v_sql_WHERE || ' AND MONTH = ''';
61. v_sql_WHERE := v_sql_WHERE || p_MONTH;
62. v_sql_WHERE := v_sql_WHERE || '''';
63. --dbms_output.put_line(p_BILL_NUM);
64. END;
65. END IF;
66. IF (p_VOL_TYPE_CODE IS NOT NULL AND LENGTH(p_VOL_TYPE_CODE) >0) THEN --凭证类别编码
67. BEGIN
68. v_sql_WHERE := v_sql_WHERE || ' AND VOUCHTYPE = ''';
69. v_sql_WHERE := v_sql_WHERE || p_VOL_TYPE_CODE;
70. v_sql_WHERE := v_sql_WHERE || '''';
71. --dbms_output.put_line(p_BILL_NUM);
72. END;
73. END IF;
74. IF (p_BILL_NUM IS NOT NULL AND LENGTH(p_BILL_NUM) >0) THEN --信息单号
75. BEGIN
76. v_sql_WHERE := v_sql_WHERE || ' AND BILLCODES LIKE ''%';
77. v_sql_WHERE := v_sql_WHERE || p_BILL_NUM;
78. v_sql_WHERE := v_sql_WHERE || '%''';
79. --dbms_output.put_line(p_BILL_NUM);
80. END;
81. END IF;
82. IF (p_VOLUME_NUM IS NOT NULL AND LENGTH(p_VOLUME_NUM) >0) THEN --册号
83. BEGIN
84. v_sql_WHERE := v_sql_WHERE || ' AND VOLUMENUM = ''';
85. v_sql_WHERE := v_sql_WHERE || p_VOLUME_NUM;
86. v_sql_WHERE := v_sql_WHERE || '''';
87. --dbms_output.put_line(p_BILL_NUM);
88. END;
89. END IF;
90. p_QUERY_SQL := 'SQL4WHERE: ' || v_sql_WHERE;
91.
92. --dbms_output.put_line(v_sql || v_sql_WHERE || p_BILL_NUM);
93. --OPEN mycur(v_WHERE);
94. OPEN mycur FOR v_sql || v_sql_WHERE;
95.
96. LOOP--循环册记录
97. fetch mycur INTO V_VOLUME_ID,v_temp1,v_tempBILLCODES ;
98. EXIT WHEN mycur%NOTFOUND;
99. V_CNT := V_CNT + 1 ;
100. --DBMS_OUTPUT.PUT_LINE( V_CNT || ':BILLCODES = ' || v_tempBILLCODES);
101. OPEN mycur_split(v_tempBILLCODES,',');
102. LOOP--循环生成每一个册的单据记录
103. fetch mycur_split INTO v_temp2 ;
104. EXIT WHEN mycur_split%NOTFOUND;
105. --DBMS_OUTPUT.PUT_LINE(' ' || v_temp2);
106. --DBMS_OUTPUT.PUT_LINE(' p_BILL_NUM= ' || p_BILL_NUM||',v_temp2='||v_temp2);
107. IF (p_BILL_NUM IS NULL OR p_BILL_NUM = TO_NUMBER(v_temp2)) THEN
108. v_temp1 := 'INSERT INTO TEMP_VOLUMES_QUERY (SELECT '''|| v_temp2 || ''',A.* FROM PUB_VOLUMES A WHERE volumeid = ' || V_VOLUME_ID || ')';--写入到临时表
109. --dbms_output.put_line( 'v_temp1=' || v_temp1);
110. execute immediate v_temp1;
111. END IF;
112. END LOOP;
113. CLOSE mycur_split;
114.
115. END LOOP;
116.
117. CLOSE mycur;
118.
119.
120.
121. --开始输出结果
122. v_sql := 'SELECT CE.DCODE,CE.VOLUMEID,CE.CORPCODE,CE.CORPNAME,QU.AREANAME,CE.YEAR,CE.MONTH,CE.BILLCODES,CE.VOUCHTYPE,SHI.ROOMNAME, ';
123. v_sql := v_sql || 'CE.VOLUMENUM,GUI.CABINETNUM,CE.CABINETLAYER FROM TEMP_VOLUMES_QUERY CE ';
124. v_sql := v_sql || 'LEFT OUTER JOIN PUB_CORPS NAME ON CE.CORPCODE = NAME.CORPCODE ';--册所属公司(产生单据的公司)
125. v_sql := v_sql || 'LEFT OUTER JOIN PUB_AREAS QU ON NAME.AREACODE=QU.AREACODE ';--册所属区域(产生单据的公司所在区域)
126. v_sql := v_sql || 'LEFT OUTER JOIN PUB_CABINETS GUI ON CE.CABINETCODE=GUI.CABINETCODE ';--册所在档案柜(保存的位置)
127. v_sql := v_sql || 'LEFT OUTER JOIN PUB_ARCHIVESROOMS SHI ON GUI.ROOMCODE = SHI.ROOMID ';--册(柜)所在档案室(保存的位置)
128. v_sql := v_sql || 'WHERE (GUI.ISMAIL = 0 OR GUI.ISSIGN = 1) ';--尚未邮寄的或者已签收的
129. v_sql := v_sql || 'AND CE.ISBORROW = ''0'' ';--尚未借出去的
130. IF (p_AREA_CODES IS NOT NULL AND LENGTH(p_AREA_CODES) >0) THEN --如果需要限制册的所属区域
131. BEGIN
132. v_sql := v_sql || 'AND QU.AREACODE IN ('|| p_AREA_CODES || ') ';
133. END;
134. END IF;
135.
136. p_QUERY_SQL := p_QUERY_SQL || ' SQL4RESULT: ' || v_sql;--返回
137.
138. OPEN p_OutCursor FOR v_sql;
139. SELECT COUNT(1) INTO V_CNT FROM TEMP_VOLUMES_QUERY;
140. dbms_output.put_line(v_sql || ',V_CNT=' || V_CNT);
141. dbms_output.put_line(V_CNT);
142. delete from TEMP_VOLUMES_QUERY;
143. COMMIT;
144.
145. end SPLIT_VOLUMES;
146.
147.end;
148./
create or replace package AMS_PKG as
type REFCURSORTYPE is REF CURSOR;
procedure SPLIT_VOLUMES (P_CORP_NAME IN varchar2,P_YEAR IN varchar2,P_MONTH IN varchar2,P_VOL_TYPE_CODE IN varchar2,P_BILL_NUM IN varchar2,P_VOLUME_NUM IN varchar2,P_AREA_CODES IN varchar2,P_QUERY_SQL out varchar2,P_OUTCURSOR out refCursorType);
end AMS_PKG;
/
CREATE OR REPLACE PACKAGE BODY "AMS_PKG" as
procedure SPLIT_VOLUMES(p_CORP_NAME IN varchar2, --查询条件,公司名称
p_YEAR IN varchar2, --查询条件,会计年度
p_MONTH IN varchar2, --查询条件,期间
p_VOL_TYPE_CODE IN varchar2, --查询条件,凭证类别编码
p_BILL_NUM IN varchar2, --查询条件,信息单号
p_VOLUME_NUM IN varchar2, --查询条件,册号
p_AREA_CODES IN varchar2, --查询条件,所在区域编码(产生册的区域),逗号分割。
--形式如 '12C01','12201','12D01','12E01','12601',存储过程中将使用in的方式进行过滤
p_QUERY_SQL out varchar2, --返回查询字符串
p_OutCursor out refCursorType --返回值
) is
v_sql varchar2(3000);
v_sql_WHERE varchar2(3000);
v_temp1 varchar2(300);
v_temp2 varchar2(300);
v_tempBILLCODES varchar2(3000);
V_CNT NUMBER(10,0);
V_VOLUME_ID NUMBER(10,0);
mycur refCursorType;
--CURSOR mycur( v varchar2) is
-- SELECT VOUCHTYPE,BILLCODES FROM PUB_VOLUMES where volumeid=v;
CURSOR mycur_split( val varchar2,splitMark varchar2) is
select * from table(myutil_split(val,splitMark));
begin
v_temp1 :='';
v_temp2 :='';
v_sql_WHERE := '';
v_tempBILLCODES := '';
V_CNT := 0;
V_VOLUME_ID := 0;--册表的系统编号
v_sql := 'SELECT VOLUMEID,VOUCHTYPE,BILLCODES FROM PUB_VOLUMES WHERE 1=1 ';
--dbms_output.put_line('p_BILL_NUM='||p_BILL_NUM);
IF (p_CORP_NAME IS NOT NULL AND LENGTH(p_CORP_NAME) >0) THEN --公司名称
BEGIN
v_sql_WHERE := v_sql_WHERE || ' AND CORPNAME LIKE ''%';
v_sql_WHERE := v_sql_WHERE || p_CORP_NAME;
v_sql_WHERE := v_sql_WHERE || '%''';
--dbms_output.put_line(p_BILL_NUM);
END;
END IF;
IF (p_YEAR IS NOT NULL AND LENGTH(p_YEAR) >0) THEN --会计年度
BEGIN
v_sql_WHERE := v_sql_WHERE || ' AND YEAR = ''';
v_sql_WHERE := v_sql_WHERE || p_YEAR;
v_sql_WHERE := v_sql_WHERE || '''';
--dbms_output.put_line(p_BILL_NUM);
END;
END IF;
IF (p_MONTH IS NOT NULL AND LENGTH(p_MONTH) >0) THEN --期间
BEGIN
v_sql_WHERE := v_sql_WHERE || ' AND MONTH = ''';
v_sql_WHERE := v_sql_WHERE || p_MONTH;
v_sql_WHERE := v_sql_WHERE || '''';
--dbms_output.put_line(p_BILL_NUM);
END;
END IF;
IF (p_VOL_TYPE_CODE IS NOT NULL AND LENGTH(p_VOL_TYPE_CODE) >0) THEN --凭证类别编码
BEGIN
v_sql_WHERE := v_sql_WHERE || ' AND VOUCHTYPE = ''';
v_sql_WHERE := v_sql_WHERE || p_VOL_TYPE_CODE;
v_sql_WHERE := v_sql_WHERE || '''';
--dbms_output.put_line(p_BILL_NUM);
END;
END IF;
IF (p_BILL_NUM IS NOT NULL AND LENGTH(p_BILL_NUM) >0) THEN --信息单号
BEGIN
v_sql_WHERE := v_sql_WHERE || ' AND BILLCODES LIKE ''%';
v_sql_WHERE := v_sql_WHERE || p_BILL_NUM;
v_sql_WHERE := v_sql_WHERE || '%''';
--dbms_output.put_line(p_BILL_NUM);
END;
END IF;
IF (p_VOLUME_NUM IS NOT NULL AND LENGTH(p_VOLUME_NUM) >0) THEN --册号
BEGIN
v_sql_WHERE := v_sql_WHERE || ' AND VOLUMENUM = ''';
v_sql_WHERE := v_sql_WHERE || p_VOLUME_NUM;
v_sql_WHERE := v_sql_WHERE || '''';
--dbms_output.put_line(p_BILL_NUM);
END;
END IF;
p_QUERY_SQL := 'SQL4WHERE: ' || v_sql_WHERE;
--dbms_output.put_line(v_sql || v_sql_WHERE || p_BILL_NUM);
--OPEN mycur(v_WHERE);
OPEN mycur FOR v_sql || v_sql_WHERE;
LOOP--循环册记录
fetch mycur INTO V_VOLUME_ID,v_temp1,v_tempBILLCODES ;
EXIT WHEN mycur%NOTFOUND;
V_CNT := V_CNT + 1 ;
--DBMS_OUTPUT.PUT_LINE( V_CNT || ':BILLCODES = ' || v_tempBILLCODES);
OPEN mycur_split(v_tempBILLCODES,',');
LOOP--循环生成每一个册的单据记录
fetch mycur_split INTO v_temp2 ;
EXIT WHEN mycur_split%NOTFOUND;
--DBMS_OUTPUT.PUT_LINE(' ' || v_temp2);
--DBMS_OUTPUT.PUT_LINE(' p_BILL_NUM= ' || p_BILL_NUM||',v_temp2='||v_temp2);
IF (p_BILL_NUM IS NULL OR p_BILL_NUM = TO_NUMBER(v_temp2)) THEN
v_temp1 := 'INSERT INTO TEMP_VOLUMES_QUERY (SELECT '''|| v_temp2 || ''',A.* FROM PUB_VOLUMES A WHERE volumeid = ' || V_VOLUME_ID || ')';--写入到临时表
--dbms_output.put_line( 'v_temp1=' || v_temp1);
execute immediate v_temp1;
END IF;
END LOOP;
CLOSE mycur_split;
END LOOP;
CLOSE mycur;
--开始输出结果
v_sql := 'SELECT CE.DCODE,CE.VOLUMEID,CE.CORPCODE,CE.CORPNAME,QU.AREANAME,CE.YEAR,CE.MONTH,CE.BILLCODES,CE.VOUCHTYPE,SHI.ROOMNAME, ';
v_sql := v_sql || 'CE.VOLUMENUM,GUI.CABINETNUM,CE.CABINETLAYER FROM TEMP_VOLUMES_QUERY CE ';
v_sql := v_sql || 'LEFT OUTER JOIN PUB_CORPS NAME ON CE.CORPCODE = NAME.CORPCODE ';--册所属公司(产生单据的公司)
v_sql := v_sql || 'LEFT OUTER JOIN PUB_AREAS QU ON NAME.AREACODE=QU.AREACODE ';--册所属区域(产生单据的公司所在区域)
v_sql := v_sql || 'LEFT OUTER JOIN PUB_CABINETS GUI ON CE.CABINETCODE=GUI.CABINETCODE ';--册所在档案柜(保存的位置)
v_sql := v_sql || 'LEFT OUTER JOIN PUB_ARCHIVESROOMS SHI ON GUI.ROOMCODE = SHI.ROOMID ';--册(柜)所在档案室(保存的位置)
v_sql := v_sql || 'WHERE (GUI.ISMAIL = 0 OR GUI.ISSIGN = 1) ';--尚未邮寄的或者已签收的
v_sql := v_sql || 'AND CE.ISBORROW = ''0'' ';--尚未借出去的
IF (p_AREA_CODES IS NOT NULL AND LENGTH(p_AREA_CODES) >0) THEN --如果需要限制册的所属区域
BEGIN
v_sql := v_sql || 'AND QU.AREACODE IN ('|| p_AREA_CODES || ') ';
END;
END IF;
p_QUERY_SQL := p_QUERY_SQL || ' SQL4RESULT: ' || v_sql;--返回
OPEN p_OutCursor FOR v_sql;
SELECT COUNT(1) INTO V_CNT FROM TEMP_VOLUMES_QUERY;
dbms_output.put_line(v_sql || ',V_CNT=' || V_CNT);
dbms_output.put_line(V_CNT);
delete from TEMP_VOLUMES_QUERY;
COMMIT;
end SPLIT_VOLUMES;
end;
/
三、结论
1、ON COMMIT DELETE ROWS 说明临时表是事务指定,每次提交后ORACLE将截断表(删除全部行)
2、ON COMMIT PRESERVE ROWS 说明临时表是会话指定,当中断会话时ORACLE将截断表。
3、临时表(无论会话级还是事务级)中的数据都是会话隔离的,不同session之间不会共享数据。
4、在存储中使用事务级临时表时,注意commit前删除掉本事务的数据,否则可能会出现数据不断增加的情况(原因尚未搞明白)。
5、 两种临时表的语法:
create global temporary table 临时表名 on commit preserve|delete rows;
用preserve时就是SESSION级的临时表,
用delete就是TRANSACTION级的临时表。
6、特性和性能(与普通表和视图的比较)
临时表只在当前连接内有效;
临时表不建立索引,所以如果数据量比较大或进行多次查询时,不推荐使用;
数据处理比较复杂的时候时表快,反之视图快点;
在仅仅查询数据的时候建议用游标: open cursor for 'sql clause';
一、Oracle临时表知识
在Oracle中,临时表分为SESSION、TRANSACTION两种,SESSION级的临时表数据在整个SESSION都存在,直到结束此次SESSION;而 TRANSACTION级的临时表数据在TRANACTION结束后消失,即COMMIT/ROLLBACK或结束SESSION都会清除 TRANACTION临时表数据。
1) 会话级临时表 示例
1创建
Sql代码
1.create global temporary table temp_tbl(col_a varchar2(30))
2.on commit preserve rows
create global temporary table temp_tbl(col_a varchar2(30))
on commit preserve rows
2插入数据
Sql代码
1.insert into temp_tbl values('test session table')
insert into temp_tbl values('test session table')
3提交
Sql代码
1.commit;
commit;
4查询
Sql代码
1.select *from temp_tbl
select *from temp_tbl
可以看到数据'test session table'记录还在。
结束SESSION,重新登录,再查询数据select *from temp_tbl,这时候记录已不存在,因为系统在结束SESSION时自动清除记录 。
2) 事务级临时表 示例
1创建
Sql代码
1.create global temporary table temp_tbl(col_a varchar2(30))
2.on commit delete rows
create global temporary table temp_tbl(col_a varchar2(30))
on commit delete rows
2插入数据
Sql代码
1.insert into temp_tbl values('test transaction table')
insert into temp_tbl values('test transaction table')
3提交
Sql代码
1.commit ;
commit ;
4查询
Sql代码
1.select *from temp_tbl
select *from temp_tbl
这时候可以看到刚才插入的记录'test transaction table'已不存在了,因为提交时已经晴空了数据库;同样,如果不提交而直接结束SESSION,重新登录记录也不存在 。
二、在Oracle存储中使用临时表的一个例子
描述:档案册借阅时,需要把册拆分成详细的单据,拆分依据是册表中的BILLCODES(若干个用逗号分割的单据号)字段,临时表用于保存拆分出来的单据信息。拆分结束后直接返回临时表的数据。
Sql代码
1.create or replace package AMS_PKG as
2. type REFCURSORTYPE is REF CURSOR;
3. procedure SPLIT_VOLUMES (P_CORP_NAME IN varchar2,P_YEAR IN varchar2,P_MONTH IN varchar2,P_VOL_TYPE_CODE IN varchar2,P_BILL_NUM IN varchar2,P_VOLUME_NUM IN varchar2,P_AREA_CODES IN varchar2,P_QUERY_SQL out varchar2,P_OUTCURSOR out refCursorType);
4.end AMS_PKG;
5./
6.CREATE OR REPLACE PACKAGE BODY "AMS_PKG" as
7. procedure SPLIT_VOLUMES(p_CORP_NAME IN varchar2, --查询条件,公司名称
8. p_YEAR IN varchar2, --查询条件,会计年度
9. p_MONTH IN varchar2, --查询条件,期间
10. p_VOL_TYPE_CODE IN varchar2, --查询条件,凭证类别编码
11. p_BILL_NUM IN varchar2, --查询条件,信息单号
12. p_VOLUME_NUM IN varchar2, --查询条件,册号
13. p_AREA_CODES IN varchar2, --查询条件,所在区域编码(产生册的区域),逗号分割。
14. --形式如 '12C01','12201','12D01','12E01','12601',存储过程中将使用in的方式进行过滤
15. p_QUERY_SQL out varchar2, --返回查询字符串
16. p_OutCursor out refCursorType --返回值
17. ) is
18.
19. v_sql varchar2(3000);
20. v_sql_WHERE varchar2(3000);
21. v_temp1 varchar2(300);
22. v_temp2 varchar2(300);
23. v_tempBILLCODES varchar2(3000);
24. V_CNT NUMBER(10,0);
25. V_VOLUME_ID NUMBER(10,0);
26. mycur refCursorType;
27. --CURSOR mycur( v varchar2) is
28. -- SELECT VOUCHTYPE,BILLCODES FROM PUB_VOLUMES where volumeid=v;
29. CURSOR mycur_split( val varchar2,splitMark varchar2) is
30. select * from table(myutil_split(val,splitMark));
31. begin
32. v_temp1 :='';
33. v_temp2 :='';
34. v_sql_WHERE := '';
35. v_tempBILLCODES := '';
36. V_CNT := 0;
37. V_VOLUME_ID := 0;--册表的系统编号
38. v_sql := 'SELECT VOLUMEID,VOUCHTYPE,BILLCODES FROM PUB_VOLUMES WHERE 1=1 ';
39. --dbms_output.put_line('p_BILL_NUM='||p_BILL_NUM);
40.
41.
42. IF (p_CORP_NAME IS NOT NULL AND LENGTH(p_CORP_NAME) >0) THEN --公司名称
43. BEGIN
44. v_sql_WHERE := v_sql_WHERE || ' AND CORPNAME LIKE ''%';
45. v_sql_WHERE := v_sql_WHERE || p_CORP_NAME;
46. v_sql_WHERE := v_sql_WHERE || '%''';
47. --dbms_output.put_line(p_BILL_NUM);
48. END;
49. END IF;
50. IF (p_YEAR IS NOT NULL AND LENGTH(p_YEAR) >0) THEN --会计年度
51. BEGIN
52. v_sql_WHERE := v_sql_WHERE || ' AND YEAR = ''';
53. v_sql_WHERE := v_sql_WHERE || p_YEAR;
54. v_sql_WHERE := v_sql_WHERE || '''';
55. --dbms_output.put_line(p_BILL_NUM);
56. END;
57. END IF;
58. IF (p_MONTH IS NOT NULL AND LENGTH(p_MONTH) >0) THEN --期间
59. BEGIN
60. v_sql_WHERE := v_sql_WHERE || ' AND MONTH = ''';
61. v_sql_WHERE := v_sql_WHERE || p_MONTH;
62. v_sql_WHERE := v_sql_WHERE || '''';
63. --dbms_output.put_line(p_BILL_NUM);
64. END;
65. END IF;
66. IF (p_VOL_TYPE_CODE IS NOT NULL AND LENGTH(p_VOL_TYPE_CODE) >0) THEN --凭证类别编码
67. BEGIN
68. v_sql_WHERE := v_sql_WHERE || ' AND VOUCHTYPE = ''';
69. v_sql_WHERE := v_sql_WHERE || p_VOL_TYPE_CODE;
70. v_sql_WHERE := v_sql_WHERE || '''';
71. --dbms_output.put_line(p_BILL_NUM);
72. END;
73. END IF;
74. IF (p_BILL_NUM IS NOT NULL AND LENGTH(p_BILL_NUM) >0) THEN --信息单号
75. BEGIN
76. v_sql_WHERE := v_sql_WHERE || ' AND BILLCODES LIKE ''%';
77. v_sql_WHERE := v_sql_WHERE || p_BILL_NUM;
78. v_sql_WHERE := v_sql_WHERE || '%''';
79. --dbms_output.put_line(p_BILL_NUM);
80. END;
81. END IF;
82. IF (p_VOLUME_NUM IS NOT NULL AND LENGTH(p_VOLUME_NUM) >0) THEN --册号
83. BEGIN
84. v_sql_WHERE := v_sql_WHERE || ' AND VOLUMENUM = ''';
85. v_sql_WHERE := v_sql_WHERE || p_VOLUME_NUM;
86. v_sql_WHERE := v_sql_WHERE || '''';
87. --dbms_output.put_line(p_BILL_NUM);
88. END;
89. END IF;
90. p_QUERY_SQL := 'SQL4WHERE: ' || v_sql_WHERE;
91.
92. --dbms_output.put_line(v_sql || v_sql_WHERE || p_BILL_NUM);
93. --OPEN mycur(v_WHERE);
94. OPEN mycur FOR v_sql || v_sql_WHERE;
95.
96. LOOP--循环册记录
97. fetch mycur INTO V_VOLUME_ID,v_temp1,v_tempBILLCODES ;
98. EXIT WHEN mycur%NOTFOUND;
99. V_CNT := V_CNT + 1 ;
100. --DBMS_OUTPUT.PUT_LINE( V_CNT || ':BILLCODES = ' || v_tempBILLCODES);
101. OPEN mycur_split(v_tempBILLCODES,',');
102. LOOP--循环生成每一个册的单据记录
103. fetch mycur_split INTO v_temp2 ;
104. EXIT WHEN mycur_split%NOTFOUND;
105. --DBMS_OUTPUT.PUT_LINE(' ' || v_temp2);
106. --DBMS_OUTPUT.PUT_LINE(' p_BILL_NUM= ' || p_BILL_NUM||',v_temp2='||v_temp2);
107. IF (p_BILL_NUM IS NULL OR p_BILL_NUM = TO_NUMBER(v_temp2)) THEN
108. v_temp1 := 'INSERT INTO TEMP_VOLUMES_QUERY (SELECT '''|| v_temp2 || ''',A.* FROM PUB_VOLUMES A WHERE volumeid = ' || V_VOLUME_ID || ')';--写入到临时表
109. --dbms_output.put_line( 'v_temp1=' || v_temp1);
110. execute immediate v_temp1;
111. END IF;
112. END LOOP;
113. CLOSE mycur_split;
114.
115. END LOOP;
116.
117. CLOSE mycur;
118.
119.
120.
121. --开始输出结果
122. v_sql := 'SELECT CE.DCODE,CE.VOLUMEID,CE.CORPCODE,CE.CORPNAME,QU.AREANAME,CE.YEAR,CE.MONTH,CE.BILLCODES,CE.VOUCHTYPE,SHI.ROOMNAME, ';
123. v_sql := v_sql || 'CE.VOLUMENUM,GUI.CABINETNUM,CE.CABINETLAYER FROM TEMP_VOLUMES_QUERY CE ';
124. v_sql := v_sql || 'LEFT OUTER JOIN PUB_CORPS NAME ON CE.CORPCODE = NAME.CORPCODE ';--册所属公司(产生单据的公司)
125. v_sql := v_sql || 'LEFT OUTER JOIN PUB_AREAS QU ON NAME.AREACODE=QU.AREACODE ';--册所属区域(产生单据的公司所在区域)
126. v_sql := v_sql || 'LEFT OUTER JOIN PUB_CABINETS GUI ON CE.CABINETCODE=GUI.CABINETCODE ';--册所在档案柜(保存的位置)
127. v_sql := v_sql || 'LEFT OUTER JOIN PUB_ARCHIVESROOMS SHI ON GUI.ROOMCODE = SHI.ROOMID ';--册(柜)所在档案室(保存的位置)
128. v_sql := v_sql || 'WHERE (GUI.ISMAIL = 0 OR GUI.ISSIGN = 1) ';--尚未邮寄的或者已签收的
129. v_sql := v_sql || 'AND CE.ISBORROW = ''0'' ';--尚未借出去的
130. IF (p_AREA_CODES IS NOT NULL AND LENGTH(p_AREA_CODES) >0) THEN --如果需要限制册的所属区域
131. BEGIN
132. v_sql := v_sql || 'AND QU.AREACODE IN ('|| p_AREA_CODES || ') ';
133. END;
134. END IF;
135.
136. p_QUERY_SQL := p_QUERY_SQL || ' SQL4RESULT: ' || v_sql;--返回
137.
138. OPEN p_OutCursor FOR v_sql;
139. SELECT COUNT(1) INTO V_CNT FROM TEMP_VOLUMES_QUERY;
140. dbms_output.put_line(v_sql || ',V_CNT=' || V_CNT);
141. dbms_output.put_line(V_CNT);
142. delete from TEMP_VOLUMES_QUERY;
143. COMMIT;
144.
145. end SPLIT_VOLUMES;
146.
147.end;
148./
create or replace package AMS_PKG as
type REFCURSORTYPE is REF CURSOR;
procedure SPLIT_VOLUMES (P_CORP_NAME IN varchar2,P_YEAR IN varchar2,P_MONTH IN varchar2,P_VOL_TYPE_CODE IN varchar2,P_BILL_NUM IN varchar2,P_VOLUME_NUM IN varchar2,P_AREA_CODES IN varchar2,P_QUERY_SQL out varchar2,P_OUTCURSOR out refCursorType);
end AMS_PKG;
/
CREATE OR REPLACE PACKAGE BODY "AMS_PKG" as
procedure SPLIT_VOLUMES(p_CORP_NAME IN varchar2, --查询条件,公司名称
p_YEAR IN varchar2, --查询条件,会计年度
p_MONTH IN varchar2, --查询条件,期间
p_VOL_TYPE_CODE IN varchar2, --查询条件,凭证类别编码
p_BILL_NUM IN varchar2, --查询条件,信息单号
p_VOLUME_NUM IN varchar2, --查询条件,册号
p_AREA_CODES IN varchar2, --查询条件,所在区域编码(产生册的区域),逗号分割。
--形式如 '12C01','12201','12D01','12E01','12601',存储过程中将使用in的方式进行过滤
p_QUERY_SQL out varchar2, --返回查询字符串
p_OutCursor out refCursorType --返回值
) is
v_sql varchar2(3000);
v_sql_WHERE varchar2(3000);
v_temp1 varchar2(300);
v_temp2 varchar2(300);
v_tempBILLCODES varchar2(3000);
V_CNT NUMBER(10,0);
V_VOLUME_ID NUMBER(10,0);
mycur refCursorType;
--CURSOR mycur( v varchar2) is
-- SELECT VOUCHTYPE,BILLCODES FROM PUB_VOLUMES where volumeid=v;
CURSOR mycur_split( val varchar2,splitMark varchar2) is
select * from table(myutil_split(val,splitMark));
begin
v_temp1 :='';
v_temp2 :='';
v_sql_WHERE := '';
v_tempBILLCODES := '';
V_CNT := 0;
V_VOLUME_ID := 0;--册表的系统编号
v_sql := 'SELECT VOLUMEID,VOUCHTYPE,BILLCODES FROM PUB_VOLUMES WHERE 1=1 ';
--dbms_output.put_line('p_BILL_NUM='||p_BILL_NUM);
IF (p_CORP_NAME IS NOT NULL AND LENGTH(p_CORP_NAME) >0) THEN --公司名称
BEGIN
v_sql_WHERE := v_sql_WHERE || ' AND CORPNAME LIKE ''%';
v_sql_WHERE := v_sql_WHERE || p_CORP_NAME;
v_sql_WHERE := v_sql_WHERE || '%''';
--dbms_output.put_line(p_BILL_NUM);
END;
END IF;
IF (p_YEAR IS NOT NULL AND LENGTH(p_YEAR) >0) THEN --会计年度
BEGIN
v_sql_WHERE := v_sql_WHERE || ' AND YEAR = ''';
v_sql_WHERE := v_sql_WHERE || p_YEAR;
v_sql_WHERE := v_sql_WHERE || '''';
--dbms_output.put_line(p_BILL_NUM);
END;
END IF;
IF (p_MONTH IS NOT NULL AND LENGTH(p_MONTH) >0) THEN --期间
BEGIN
v_sql_WHERE := v_sql_WHERE || ' AND MONTH = ''';
v_sql_WHERE := v_sql_WHERE || p_MONTH;
v_sql_WHERE := v_sql_WHERE || '''';
--dbms_output.put_line(p_BILL_NUM);
END;
END IF;
IF (p_VOL_TYPE_CODE IS NOT NULL AND LENGTH(p_VOL_TYPE_CODE) >0) THEN --凭证类别编码
BEGIN
v_sql_WHERE := v_sql_WHERE || ' AND VOUCHTYPE = ''';
v_sql_WHERE := v_sql_WHERE || p_VOL_TYPE_CODE;
v_sql_WHERE := v_sql_WHERE || '''';
--dbms_output.put_line(p_BILL_NUM);
END;
END IF;
IF (p_BILL_NUM IS NOT NULL AND LENGTH(p_BILL_NUM) >0) THEN --信息单号
BEGIN
v_sql_WHERE := v_sql_WHERE || ' AND BILLCODES LIKE ''%';
v_sql_WHERE := v_sql_WHERE || p_BILL_NUM;
v_sql_WHERE := v_sql_WHERE || '%''';
--dbms_output.put_line(p_BILL_NUM);
END;
END IF;
IF (p_VOLUME_NUM IS NOT NULL AND LENGTH(p_VOLUME_NUM) >0) THEN --册号
BEGIN
v_sql_WHERE := v_sql_WHERE || ' AND VOLUMENUM = ''';
v_sql_WHERE := v_sql_WHERE || p_VOLUME_NUM;
v_sql_WHERE := v_sql_WHERE || '''';
--dbms_output.put_line(p_BILL_NUM);
END;
END IF;
p_QUERY_SQL := 'SQL4WHERE: ' || v_sql_WHERE;
--dbms_output.put_line(v_sql || v_sql_WHERE || p_BILL_NUM);
--OPEN mycur(v_WHERE);
OPEN mycur FOR v_sql || v_sql_WHERE;
LOOP--循环册记录
fetch mycur INTO V_VOLUME_ID,v_temp1,v_tempBILLCODES ;
EXIT WHEN mycur%NOTFOUND;
V_CNT := V_CNT + 1 ;
--DBMS_OUTPUT.PUT_LINE( V_CNT || ':BILLCODES = ' || v_tempBILLCODES);
OPEN mycur_split(v_tempBILLCODES,',');
LOOP--循环生成每一个册的单据记录
fetch mycur_split INTO v_temp2 ;
EXIT WHEN mycur_split%NOTFOUND;
--DBMS_OUTPUT.PUT_LINE(' ' || v_temp2);
--DBMS_OUTPUT.PUT_LINE(' p_BILL_NUM= ' || p_BILL_NUM||',v_temp2='||v_temp2);
IF (p_BILL_NUM IS NULL OR p_BILL_NUM = TO_NUMBER(v_temp2)) THEN
v_temp1 := 'INSERT INTO TEMP_VOLUMES_QUERY (SELECT '''|| v_temp2 || ''',A.* FROM PUB_VOLUMES A WHERE volumeid = ' || V_VOLUME_ID || ')';--写入到临时表
--dbms_output.put_line( 'v_temp1=' || v_temp1);
execute immediate v_temp1;
END IF;
END LOOP;
CLOSE mycur_split;
END LOOP;
CLOSE mycur;
--开始输出结果
v_sql := 'SELECT CE.DCODE,CE.VOLUMEID,CE.CORPCODE,CE.CORPNAME,QU.AREANAME,CE.YEAR,CE.MONTH,CE.BILLCODES,CE.VOUCHTYPE,SHI.ROOMNAME, ';
v_sql := v_sql || 'CE.VOLUMENUM,GUI.CABINETNUM,CE.CABINETLAYER FROM TEMP_VOLUMES_QUERY CE ';
v_sql := v_sql || 'LEFT OUTER JOIN PUB_CORPS NAME ON CE.CORPCODE = NAME.CORPCODE ';--册所属公司(产生单据的公司)
v_sql := v_sql || 'LEFT OUTER JOIN PUB_AREAS QU ON NAME.AREACODE=QU.AREACODE ';--册所属区域(产生单据的公司所在区域)
v_sql := v_sql || 'LEFT OUTER JOIN PUB_CABINETS GUI ON CE.CABINETCODE=GUI.CABINETCODE ';--册所在档案柜(保存的位置)
v_sql := v_sql || 'LEFT OUTER JOIN PUB_ARCHIVESROOMS SHI ON GUI.ROOMCODE = SHI.ROOMID ';--册(柜)所在档案室(保存的位置)
v_sql := v_sql || 'WHERE (GUI.ISMAIL = 0 OR GUI.ISSIGN = 1) ';--尚未邮寄的或者已签收的
v_sql := v_sql || 'AND CE.ISBORROW = ''0'' ';--尚未借出去的
IF (p_AREA_CODES IS NOT NULL AND LENGTH(p_AREA_CODES) >0) THEN --如果需要限制册的所属区域
BEGIN
v_sql := v_sql || 'AND QU.AREACODE IN ('|| p_AREA_CODES || ') ';
END;
END IF;
p_QUERY_SQL := p_QUERY_SQL || ' SQL4RESULT: ' || v_sql;--返回
OPEN p_OutCursor FOR v_sql;
SELECT COUNT(1) INTO V_CNT FROM TEMP_VOLUMES_QUERY;
dbms_output.put_line(v_sql || ',V_CNT=' || V_CNT);
dbms_output.put_line(V_CNT);
delete from TEMP_VOLUMES_QUERY;
COMMIT;
end SPLIT_VOLUMES;
end;
/
三、结论
1、ON COMMIT DELETE ROWS 说明临时表是事务指定,每次提交后ORACLE将截断表(删除全部行)
2、ON COMMIT PRESERVE ROWS 说明临时表是会话指定,当中断会话时ORACLE将截断表。
3、临时表(无论会话级还是事务级)中的数据都是会话隔离的,不同session之间不会共享数据。
4、在存储中使用事务级临时表时,注意commit前删除掉本事务的数据,否则可能会出现数据不断增加的情况(原因尚未搞明白)。
5、 两种临时表的语法:
create global temporary table 临时表名 on commit preserve|delete rows;
用preserve时就是SESSION级的临时表,
用delete就是TRANSACTION级的临时表。
6、特性和性能(与普通表和视图的比较)
临时表只在当前连接内有效;
临时表不建立索引,所以如果数据量比较大或进行多次查询时,不推荐使用;
数据处理比较复杂的时候时表快,反之视图快点;
在仅仅查询数据的时候建议用游标: open cursor for 'sql clause';
相关推荐
解决 Oracle 临时表空间满的问题需要通过查看当前数据库的默认临时表空间、查看当前临时表空间的大小、创建新的临时表空间、将新建的临时表空间设置为数据库的默认临时表空间、删除原来的临时表空间、创建新的临时表...
Oracle 临时表空间不足和批处理缓慢问题探讨 本文探讨了 Oracle 临时表空间不足和批处理缓慢问题的原因和解决方法。通过分析和测试,发现了问题的根源在于应用逻辑方面,具体来说是 SQL 语句的编写问题。通过编写...
本文将详细介绍Oracle临时表的创建方法、使用场景以及优缺点,帮助读者更好地理解和运用这一特性。 #### 二、Oracle临时表概述 Oracle临时表是一种特殊的表,用于存储临时数据,通常用于事务处理或特定会话期间的...
### Oracle临时表详解 #### 一、Oracle临时表概述 在Oracle数据库中,临时表是一种特殊类型的数据表,主要用于存储暂时性的数据。与永久表不同的是,临时表中的数据不会一直保留,而是根据不同的条件(如事务结束...
Oracle 临时表用法 Oracle 临时表是一种特殊的表结构,它可以在数据库中临时存储数据,用于实现一些特定的应用场景。下面是 Oracle 临时表的详细知识点: 创建临时表 创建临时表的语法为: ``` CREATE GLOBAL ...
"Oracle 临时表(事务级、会话级)" Oracle 临时表是 Oracle 数据库中的一种特殊类型的表,它可以保存一个会话或事务中的数据。当会话或事务结束时,临时表中的数据自动清空,但是临时表的结构和元数据还存储在...
Oracle 临时表空间是Oracle...总之,理解并正确使用Oracle临时表空间是确保数据库高效运行的关键。通过对临时表空间的合理配置和管理,可以有效地提升数据库的响应速度,降低系统资源消耗,从而优化整体的数据库性能。
临时表本质上是一种cache的表现形式,Oracle的临时表都是事先建好的,一旦用了临时表,存放的是和本会话相关的数据,没有人会傻乎乎地用临时表来保存本应该共享的数据。 with子查询实际上也是用了临时表,...
临时表的应用 1)、当某一个SQL语句关联的表在2张及以上,并且和一些小表关联。可以采用将大表进行分拆并且得到比较小的结果集合存放在临时表中。 2)、程序执行过程中可能需要存放一些临时的数据,这些数据在整个...
### Oracle 临时表空间管理与释放脚本解析 在Oracle数据库管理中,临时表空间(Temporary Tablespace)的管理是一项非常重要的任务。合理的管理和优化临时表空间不仅可以提高系统的性能,还可以帮助解决空间不足等...
Oracle中的临时表是一种特殊的数据结构,用于存储会话或事务期间的数据,这些数据仅对当前会话可见,并在特定条件下自动清除。Oracle提供两种类型的临时表:事务型和会话型。 事务型临时表在事务开始时创建,插入的...
### Oracle 临时表空间管理详解 #### 一、概述 Oracle 数据库中的临时表空间主要用于存储临时对象,如排序操作、表连接等过程中产生的临时数据。这些数据在事务结束后会被自动清除,不会占用永久存储空间。正确管理...
Oracle Temporary Tables,也称为Oracle临时表,是Oracle数据库系统中用于存储临时数据的特殊类型表。它们主要用于处理会话级别的数据,这些数据在特定会话或事务结束后会被自动清理,从而减少了对永久表的负担和...
**二、Oracle临时表** 临时表在Oracle中用于在单个会话中存储临时数据,这些数据只对创建它们的会话可见,会话结束时,临时表及其数据都会被自动删除。 1. **创建临时表**:使用`CREATE GLOBAL TEMPORARY TABLE`...
Oracle Temporary Tables,也称为Oracle临时表,是在Oracle数据库中用于临时存储数据的特殊表。它们主要用在处理大型数据集时提高性能,特别是在复杂的查询和存储过程中。临时表的生命周期和可见性根据创建时指定的...
本篇文章将深入探讨Oracle临时表的使用,并通过一个使用游标(CURSOR)返回结果集的例子来进一步理解其用法。 首先,让我们了解如何创建Oracle临时表。临时表的创建语法与普通表类似,但我们需要使用`GLOBAL ...
Oracle数据库中的临时表是一种特殊的表类型,主要用于存储在特定会话或事务期间产生的临时数据。与常规的永久表相比,临时表的数据不会永久保存,而是会在会话结束或事务完成时自动清除,无需用户手动删除。 1. **...
创建Oracle临时表的语法是`CREATE GLOBAL TEMPORARY TABLE`,并且可以指定`ON COMMIT`子句来决定数据何时清除,交易级别(Transaction)或会话级别(Session)。交易级别意味着在每次提交时清空表,而会话级别则是在...
oracle查找定位占用临时表空间较大的SQL语句方法,包括:(1)造成临时表空间暴涨的SQL还在运行中(2)造成临时表空间暴涨的SQL已经运行过了。