首页 文章

在Oracle db上获取插入的记录ID

提问于
浏览
2

我在数据库服务器上使用Oracle,从XP客户端使用VB6和ADO . 在一个事务中,我将一条记录插入到父表中,该表具有触发器和序列以创建唯一的记录,然后该记录用于与子表的关系,以便对子表进行可变数量的插入 . 为了提高性能,这是从我的客户端应用程序发送的一个执行命令 . 例如(简化示例):

声明Recordid int;
开始
插入ParentTable(字段列表)值(数据列表);
从Dual中选择ParentTableSequence.currVal到Recordid;
插入到ChildTable(RecordID,字段列表)值(Recordid,数据列表);
插入到ChildTable(RecordID,字段列表)值(Recordid,数据列表);
...多个可变数量的其他ChildTable插入
承诺;
结束;

这工作正常 . 我的问题是:我还需要向客户端返回为插入创建的Recordid . 在SQL Server上,我可以在提交之后向Scope_Identity()添加类似于将记录集返回到具有唯一ID的客户端 .

但是我如何为Oracle做类似的事情(不必是记录集,我只需要那个长整数值)?我根据搜索网络的结果尝试了很多东西,但未能找到解决方案 .

谢谢!
MarkL

1 回答

  • 6

    这两行可以压缩成一个语句:

    --  insert into ParentTable (field list) Values (data list);
    --  Select ParentTableSequence.currVal into Recordid from dual;
    insert into ParentTable (field list) Values (data list)
      returning ParentTable.ID into Recordid;
    

    如果要将ID传递回调用程序,则需要将程序定义为存储过程或函数,分别将Recordid作为OUT参数或RETURN值返回 .

    Edit

    MarkL评论说:

    我相信,这更像是一个Oracle PL / SQL问题 .

    我承认我对ADO一无所知,所以我不知道以下示例是否适用于您的情况 . 它涉及构建一些基础结构,允许我们将一组值传递给一个过程 . 以下示例创建一个新部门,促进现有员工管理它并分配两个新员工 .

    SQL> create or replace type new_emp_t as object
      2      (ename varchar2(10)
      3       , sal number (7,2)
      4       , job varchar2(10));
      5  /
    
    Type created.
    
    SQL>
    SQL> create or replace type new_emp_nt as table of new_emp_t;
      2  /
    
    Type created.
    
    SQL>
    SQL> create or replace procedure pop_new_dept
      2      (p_dname in dept.dname%type
      3       , p_loc in dept.loc%type
      4       , p_mgr in emp.empno%type
      5       , p_staff in new_emp_nt
      6       , p_deptno out dept.deptno%type)
      7  is
      8      l_deptno  dept.deptno%type;
      9  begin
     10      insert into dept
     11          (dname, loc)
     12      values
     13          (p_dname, p_loc)
     14      returning deptno into l_deptno;
     15      update emp
     16          set deptno = l_deptno
     17              , job = 'MANAGER'
     18              , mgr = 7839
     19          where empno = p_mgr;
     20      forall i in p_staff.first()..p_staff.last()
     21          insert into emp
     22              (ename
     23                  , sal
     24                  , job
     25                  , hiredate
     26                  , mgr
     27                  , deptno)
     28          values
     29              (p_staff(i).ename
     30                , p_staff(i).sal
     31                , p_staff(i).job
     32                , sysdate
     33                , p_mgr
     34                , l_deptno);
     35      p_deptno := l_deptno;
     36  end pop_new_dept;
     37  /
    
    Procedure created.
    
    SQL>
    SQL> set serveroutput on
    SQL>
    SQL> declare
      2      dept_staff new_emp_nt;
      3      new_dept dept.deptno%type;
      4  begin
      5      dept_staff := new_emp_nt(new_emp_t('MARKL', 4200, 'DEVELOPER')
      6                               , new_emp_t('APC', 2300, 'DEVELOPER'));
      7      pop_new_dept('IT', 'BRNO', 7844, dept_staff, new_dept);
      8      dbms_output.put_line('New DEPTNO = '||new_dept);
      9  end;
     10  /
    New DEPTNO = 70
    
    PL/SQL procedure successfully completed.
    
    SQL>
    

    DEPT和EMP的主键都是通过触发器分配的 . FORALL 语法是一种非常有效的插入记录的方法(它也适用于 UPDATEDELETE ) . 这可以写为 FUNCTION 来代替返回新的DEPTNO,但在插入,更新或删除时使用 PROCEDURE 通常被认为是更好的做法 .

    这将是我的首选方法,但我承认这不是每个人的口味 .

    Edit 2

    在性能方面,使用 FORALL 的批量操作肯定比少数单个插件更好 . 在SQL中,set操作总是比逐个记录更可取 . 但是,如果我们每次只处理少量记录时很难注意到差异 .

    构建PL / SQL集合(您认为SQL Server中的临时表)在内存方面可能很昂贵 . 如果有许多用户运行代码,则尤其如此,因为它来自会话级别的内存分配,而不是共享全局区域 . 当我们处理大量记录时,最好以块的形式填充数组,可能使用带有 LIMIT 子句的 BULK COLLECT 语法 .

    Oracle在线文档集很不错 . PL / SQL Developer's Guide有一整章关于集合 . Find out more .

相关问题