Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在'中使用记录数组;在';Oracle中的运算符_Oracle_Plsql - Fatal编程技术网

在'中使用记录数组;在';Oracle中的运算符

在'中使用记录数组;在';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

我有一个表Course,它有列DepId和Course以及一些其他值。我需要在这个表中搜索一组(DepId,当然)。此集合将在运行时确定

我想在一个过程中编写一个查询来获取与上述集合相关的所有记录。 例如,表中的数据有如

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中的示例)的讨论与对于复杂示例的讨论几乎相同。使用阵列构建的解决方案具有良好的可扩展性和动态性,如果在设计时稍加高级规划

一些预先的设计决策
  • 有实际的集合类型称为
    数组
    关联数组
    。我选择使用
    嵌套表类型
    ,因为它们可以直接
    SQL
    查询。在某些方面,它们表现出“类似数组”的行为。还可以通过Oracle参考资料研究其他权衡

  • 应用于搜索
    课程表
    的查询将应用
    联接
    条件,而不是
    列表内
    方法

  • 使用
    存储过程
    类型化对象可以改进数据库响应。过程调用中的查询可以利用和重用已编译的代码及其缓存的执行计划

选择正确的集合或数组类型 Oracle中有许多用于将变量存储到内存中的集合类型可供选择。每种方法都有优点和局限性。有一个很好的例子,通过选择一种变量集合类型而不是另一种变量集合类型,详细说明了开发人员可以期望的内容

使用嵌套表类型管理多值变量 对于这个解决方案,我选择使用
嵌套表
,因为它们可以通过
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