在'中使用记录数组;在';Oracle中的运算符
我有一个表Course,它有列DepId和Course以及一些其他值。我需要在这个表中搜索一组(DepId,当然)。此集合将在运行时确定 我想在一个过程中编写一个查询来获取与上述集合相关的所有记录。 例如,表中的数据有如在'中使用记录数组;在';Oracle中的运算符,oracle,plsql,Oracle,Plsql,我有一个表Course,它有列DepId和Course以及一些其他值。我需要在这个表中搜索一组(DepId,当然)。此集合将在运行时确定 我想在一个过程中编写一个查询来获取与上述集合相关的所有记录。 例如,表中的数据有如 DepId Course ... ------------------ 1 A 2 B 3 C 4 D 5 E 6 F 现在,我只想搜索以下记录: DepId Cou
DepId Course ...
------------------
1 A
2 B
3 C
4 D
5 E
6 F
现在,我只想搜索以下记录:
DepId Course ...
------------------
1 A
4 D
写上述查询最有效的方法是什么?
我正在考虑创建一个记录数组并将其传递给“in”操作符。但我没有得到任何这样的例子。有人能在这方面指导我吗
谢谢这是我过去在类似于你的情况下使用过的东西。希望能有帮助 此方法的主要好处是,如果只传递一个参数,它仍将返回该参数的所有记录。这样,一个带有5个输入参数的单一存储过程就可以用来搜索所有输入组合 只需调用传入集合的存储过程,并应返回符合条件的所有值
- usp_自定义_搜索'1','A'
- usp_自定义_搜索'4','D'
- usp_自定义_搜索“4”,空
- usp\u自定义搜索空,'A'
- 等
CREATE OR REPLACE PROCEDURE custom_search (
dep_id IN VARCHAR2,
course_id IN VARCHAR2,
result_set OUT SYS_REFCURSOR)
BEGIN
query_str VARCHAR2(1000);
query_str := 'SELECT';
query_str := query_str || ' DepId, Course';
query_str := query_str || ' FROM Course';
query_str := query_str || ' WHERE 1=1';
IF (dep_id is not null) then query_str := query_str || ' AND DepId = ''' || dep_id || ''''; END IF;
IF (course_id is not null) then query_str := query_str || ' AND Course = ''' || course_id || ''''; END IF;
open result_set for query_str;
END custom_search;
/
利用Oracle集合构建阵列类型的解决方案
您的问题的答案是是,在解决输入值和输出值中存在多个值或同时存在多个值的问题时,维度变量(如数组
和集合
)是可行的数据类型
另外一个好消息是,对于一个简单示例(如OP中的示例)的讨论与对于复杂示例的讨论几乎相同。使用阵列构建的解决方案具有良好的可扩展性和动态性,如果在设计时稍加高级规划
一些预先的设计决策
- 有实际的集合类型称为
和数组
。我选择使用关联数组
,因为它们可以直接嵌套表类型
查询。在某些方面,它们表现出“类似数组”的行为。还可以通过Oracle参考资料研究其他权衡SQL
- 应用于搜索
的查询将应用课程表
条件,而不是联接
方法列表内
- 使用
类型化对象可以改进数据库响应。过程调用中的查询可以利用和重用已编译的代码及其缓存的执行计划存储过程
嵌套表
,因为它们可以通过SQL
命令直接访问。在尝试了几种不同的方法之后,我注意到简单的SQL可访问性使生成的代码更加清晰
缺点是,您会注意到,在声明嵌套表类型的实例、初始化每个实例以及通过添加新值来管理其大小方面,到处都有一些开销
在任何情况下,如果您预期输入变量或值(我们的输出)的数量未知,那么对于您的代码来说,任何类型的数组类型的数据类型(集合)都是更灵活的结构。最终可能需要更少的维护
示例:存储过程搜索查询
自定义类型定义
CREATE OR REPLACE TYPE "COURSE_REC_TYPE" IS OBJECT (DEPID NUMBER(10,0), COURSE VARCHAR2(10));
CREATE OR REPLACE TYPE "COURSE_TBL_TYPE" IS TABLE of course_rec_type;
CREATE OR REPLACE TYPE "NUM_TBL_TYPE" IS TABLE of INTEGER;
过程源代码
create or replace PROCEDURE ZZ_PROC_COURSE_SEARCH IS
my_input course_tbl_type:= course_tbl_type();
my_output course_tbl_type:= course_tbl_type();
cur_loop_counter pls_integer;
c_output_template constant varchar2(100):=
'DEPID: <<DEPID>>, COURSE: <<COURSE>>';
v_output VARCHAR2(200);
CURSOR find_course_cur IS
SELECT crs.depid, crs.course
FROM zz_course crs,
(SELECT depid, course
FROM TABLE (CAST (my_input AS course_tbl_type))
) search_values
WHERE crs.depid = search_values.depid
AND crs.course = search_values.course;
BEGIN
my_input.extend(2);
my_input(1):= course_rec_type(1, 'A');
my_input(2):= course_rec_type(4, 'D');
cur_loop_counter:= 0;
for i in find_course_cur
loop
cur_loop_counter:= cur_loop_counter + 1;
my_output.extend;
my_output(cur_loop_counter):= course_rec_type(i.depid, i.course);
end loop;
for j in my_output.first .. my_output.last
loop
v_output:= replace(c_output_template, '<<DEPID>>', to_char(my_output(j).depid));
v_output:= replace(v_output, '<<COURSE>>', my_output(j).course);
dbms_output.put_line(v_output);
end loop;
end ZZ_PROC_COURSE_SEARCH;
我的评论:我对输入变量的存储方式不是特别满意。在将值“加载”到嵌套表结构中时出现了一种笨拙的问题。。。如果您可以考虑使用单个搜索关键字而不是复合对(即,DeID和Read),问题会浓缩成更简单的形式。
使用单个搜索值修改光标
这是对OP表设计的建议修改。添加一个唯一的键id列(RecId
),以表示DepId
和课程
的每个唯一组合
请注意,RecId列表示一个代理键
,该代理键除了作为唯一赋值的属性外,不应有任何内部含义
自定义类型定义
CREATE OR REPLACE TYPE "COURSE_REC_TYPE" IS OBJECT (DEPID NUMBER(10,0), COURSE VARCHAR2(10));
CREATE OR REPLACE TYPE "COURSE_TBL_TYPE" IS TABLE of course_rec_type;
CREATE OR REPLACE TYPE "NUM_TBL_TYPE" IS TABLE of INTEGER;
删除数组变量
create or replace PROCEDURE ZZ_PROC_COURSE_SEARCH IS
my_input course_tbl_type:= course_tbl_type();
my_output course_tbl_type:= course_tbl_type();
cur_loop_counter pls_integer;
c_output_template constant varchar2(100):=
'DEPID: <<DEPID>>, COURSE: <<COURSE>>';
v_output VARCHAR2(200);
CURSOR find_course_cur IS
SELECT crs.depid, crs.course
FROM zz_course crs,
(SELECT depid, course
FROM TABLE (CAST (my_input AS course_tbl_type))
) search_values
WHERE crs.depid = search_values.depid
AND crs.course = search_values.course;
BEGIN
my_input.extend(2);
my_input(1):= course_rec_type(1, 'A');
my_input(2):= course_rec_type(4, 'D');
cur_loop_counter:= 0;
for i in find_course_cur
loop
cur_loop_counter:= cur_loop_counter + 1;
my_output.extend;
my_output(cur_loop_counter):= course_rec_type(i.depid, i.course);
end loop;
for j in my_output.first .. my_output.last
loop
v_output:= replace(c_output_template, '<<DEPID>>', to_char(my_output(j).depid));
v_output:= replace(v_output, '<<COURSE>>', my_output(j).course);
dbms_output.put_line(v_output);
end loop;
end ZZ_PROC_COURSE_SEARCH;
这将通过过程调用的输入参数直接传递
-- REMOVE
my_input course_tbl_type:= course_tbl_type();
加载和显示输入参数数组(嵌套表)
以下内容可以从主过程中删除,并作为过程调用的一部分显示
BEGIN
my_input.extend(2);
my_input(1):= course_rec_type(1, 'A');
my_input(2):= course_rec_type(4, 'D');
变成:
create or replace PROCEDURE ZZ_PROC_COURSE_SEARCH (p_search_ids IN num_tbl_type) IS...
及
更改内部光标定义
光标看起来大致相同。现在只有一个搜索参数,您可以同样轻松地使用列表中的
CURSOR find_course_cur IS
SELECT crs.depid, crs.course
FROM zz_course_new crs,
(SELECT column_value as recid
FROM TABLE (CAST (p_search_ids AS num_tbl_type))
) search_values
WHERE crs.recid = search_values.recid;
实际搜索调用和输出
此操作的搜索部分现在是独立的和动态的。它不需要改变。所有更改都发生在调用PL/SQL块中,其中搜索ID值更易于读取和更改
DECLARE
my_input_external num_tbl_type:= num_tbl_type();
BEGIN
my_input_external.extend(3);
my_input_external:= num_tbl_type(1,3,22);
ZZ_PROC_COURSE_SEARCH (p_search_ids => my_input_external);
END;
-- The OUTPUT (Currently set to DBMS_OUT)
DEPID: 1, COURSE: A
DEPID: 4, COURSE: D
DEPID: 7, COURSE: G
Statement processed.
0.01 seconds