【问题标题】:How it insert result of select statement into table of records (associative array)如何将 select 语句的结果插入记录表(关联数组)
【发布时间】:2019-09-02 19:30:14
【问题描述】:

我正在研究 oracle 的 HR 计划。我有记录表

   type emp_record is RECORD(emp_first_name employees.first_name%type,
                       emp_last_name  employees.last_name%type,
                       );



    type emp_record_table is table of emp_record
       index by pls_integer;

我想将下一个 select 语句的结果插入到 emp_record_table 中

   select first_name, last_name
   from employees
   where department_id=30;

你能解释一下如何解决这个问题吗?谢谢。

【问题讨论】:

  • 必须是关联数组吗?使用嵌套表,代码会更简单。
  • 它必须是记录表,因为我知道这仅适用于关联数组

标签: oracle plsql collections record


【解决方案1】:

最简单的方法是使用批量收集:

declare

  type emp_record is RECORD(emp_first_name employees.first_name%type,
                            emp_last_name  employees.last_name%type
                       );
  type emp_record_table is table of emp_record
       index by pls_integer;

  l_recs emp_record_table;

begin

  select first_name, last_name
  bulk collect into l_recs
  from employees
  where department_id=30;

  for idx in l_recs.first()..l_recs.last() loop
    dbms_output.put_line(l_recs(idx).emp_first_name ||' '|| l_recs(idx).emp_last_name);
  end loop;

end;       
/

请注意,您实际上并不需要关联数组来处理这样的记录。你可以放弃index by pls_integer,一切仍然可以正常工作。关联数组的价值在于我们需要维护对特定行的访问路径。例如,我们可能想使用employees 表的主键来索引数组。这将创建一个稀疏数组,因为不能保证选定的员工 ID 形成一个连续的序列。因此,整理数组的逻辑更加冗长:

declare

  type emp_record is RECORD(emp_first_name employees.first_name%type,
                            emp_last_name  employees.last_name%type
                       );
  type emp_record_table is table of emp_record
       index by pls_integer;

  l_recs emp_record_table;
  idx pls_integer;

begin

  for r in (select emp_id, first_name, last_name
            from employees
            where department_id=30 )
  loop
      l_recs(r.emp_id).emp_first_name := r.first_name;
      l_recs(r.emp_id).emp_last_name  := r.last_name;
  end loop;

  idx := l_recs.first();
  while idx is not null loop
    dbms_output.put_line(l_recs(idx).emp_first_name ||' '|| l_recs(idx).emp_last_name);
    idx := l_recs.next(idx);
  end loop;

end;       
/

这里是a demo on db<>fiddle

【讨论】:

    【解决方案2】:

    Oracle 设置

    CREATE TABLE employees (
      id         NUMBER(8,0) PRIMARY KEY,
      first_name VARCHAR2(50),
      last_name  VARCHAR2(80)
    );
    
    CREATE PACKAGE test_pkg IS
      TYPE emp_record IS RECORD(
        emp_first_name employees.first_name%type,
        emp_last_name  employees.last_name%type
      );
    
      TYPE emp_record_table IS TABLE OF emp_record INDEX BY pls_integer;
    END;
    /
    
    INSERT INTO employees( id, first_name, last_name )
      SELECT -1, 'a', 'aaa' FROM DUAL UNION ALL
      SELECT +3, 'b', 'bbb' FROM DUAL;
    

    PL/SQL 块

    DECLARE
      x PLS_INTEGER;
      emps test_pkg.emp_record_table;
    BEGIN
      -- Populate the associative array
      FOR row IN ( SELECT * FROM employees ) LOOP
        emps(row.id).emp_first_name := row.first_name;
        emps(row.id).emp_last_name  := row.last_name;
      END LOOP;
    
      -- Read the associative array
      x := emps.FIRST;
      WHILE x IS NOT NULL LOOP
        DBMS_OUTPUT.PUT_LINE( x || ': ' || emps(x).emp_first_name || ' ' || emps(x).emp_last_name );
        x := emps.NEXT(x);
      END LOOP;
    END;
    /
    

    输出

    -1:啊啊啊 3:BBBB

    db小提琴here

    【讨论】:

      【解决方案3】:

      该操作不需要关联数组。嵌套表将是完美的。只需将您的表类型声明如下:

      type emp_record_table is table of emp_record;
      

      首先你必须声明你创建的类型的表。现在您只声明了这些记录的类型或记录以及表的类型。你还没有你的桌子。您可以在DECLARE 部分中按照以下方式进行声明:

      l_emp_table emp_record_table;
      

      然后初始化它:

      l_emp_table := emp_record_table();
      

      然后您创建将从您的SELECT 查询中获取数据的游标。如果你不知道怎么做,请阅读游标声明和获取。

      下一步将是:为每个游标行将其数据插入表中。您编写简单的循环,将执行以下步骤:

      1. 扩展您声明的表l_emp_table.extend()
      2. 将数据保存到表l_emp_table(i).emp_first_name := FETCHED_ROW.first_name等等...

      【讨论】:

        猜你喜欢
        • 2021-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-02
        • 1970-01-01
        • 1970-01-01
        • 2016-09-01
        • 1970-01-01
        相关资源
        最近更新 更多