如何从oracle合并查询返回主键

如何从oracle合并查询返回主键,oracle,merge,oracle10g,sequence,sql-returning,Oracle,Merge,Oracle10g,Sequence,Sql Returning,我想从oracle合并查询返回主键。 如果不存在,我将使用一条语句来插入,我不想使用过程或函数来插入 这是示例查询 merge into myTable e using (select :empname name from dual) s on (UPPER(TRIM(e.empname)) = UPPER(TRIM(s.name))) when not matched then insert (empname) values (s.name) 我需要得到myTable的

我想从oracle合并查询返回主键。 如果不存在,我将使用一条语句来插入,我不想使用过程或函数来插入

这是示例查询

merge into myTable e
  using (select :empname name from dual) s
  on (UPPER(TRIM(e.empname)) = UPPER(TRIM(s.name)))
  when not matched then insert (empname) 
    values (s.name)
我需要得到myTable的另一个主键字段。使用序列和触发器插入主键

我尝试将
返回empID添加到:empID
中,但出现了错误

出现了问题

  • 合并到
    不支持
    返回到
    ,因此不起作用
  • 序列不会一直被使用,因为它只在插入新记录时使用
  • 获取序列的现有值不起作用,因为如果要在当前会话中尚未使用序列时查询sequence.currval,则会出现错误
  • 要解决这个问题:

  • 使用过程或匿名程序块尝试更新该值。如果更新后
    sql%rowcount
    返回0,则执行插入
  • 使用选择(查询
    上限(修剪(名称))
    )查找已更新的记录
    你可以试试这个。您需要声明一个包来捕获您的id,否则SQL语句将看不到该包,您将得到一个错误:

    pls-00231:函数名称不能在SQL中使用

    因此,首先创建包含要捕获的函数的包,然后从merge语句访问ID:

    CREATE OR REPLACE PACKAGE CaptureId
    AS
       FUNCTION SaveId(newId IN NUMBER) RETURN NUMBER;
       FUNCTION GetId RETURN NUMBER;
    END;
    
    CREATE OR REPLACE PACKAGE BODY CaptureId
    AS
       capturedId NUMBER(10);
    
       FUNCTION SaveId(newId IN NUMBER) RETURN NUMBER IS
       BEGIN
          capturedId := newId;
          RETURN capturedId;
       END;
    
       FUNCTION GetId RETURN NUMBER IS
       BEGIN
          RETURN capturedId;
       END;
    END;
    
    给出一个简单的表和序列生成器,定义如下:

    CREATE TABLE EMPLOYEE
    (
        EMPLOYEE_ID NUMBER(10) NOT NULL,
        FIRST_NAME VARCHAR2(120) NOT NULL,
        LAST_NAME VARCHAR2(120) NOT NULL,
        CONSTRAINT PK_EMPLOYEE PRIMARY KEY (EMPLOYEE_ID) ENABLE
    );
    
    CREATE SEQUENCE SEQ_EMPLOYEE;
    
    然后,您可以将匿名块中的包与merge语句一起使用,以捕获id并返回它。请注意,这是一个非常简单的示例,它不适用于数组绑定变量,除非您重新编写包以将ID捕获到表类型中。如果我有机会,我可以试着用一个例子来说明这一点

    BEGIN
       MERGE INTO EMPLOYEE USING (SELECT CaptureId.SaveId(:myInputId) AS EMPLOYEE_ID,
                                         :myFirstName as FIRST_NAME,
                                         :myLastName as LAST_NAME
                                    FROM DUAL) B
          ON (A.EMPLOYEE_ID = B.EMPLOYEE_ID)
       WHEN NOT MATCHED THEN
           INSERT (EMPLOYEE_ID,
                   FIRST_NAME,
                   LAST_NAME)
           VALUES (CaptureId.SaveId(SEQ_EMPLOYEE.NEXTVAL),
                   B.FIRST_NAME,
                   B.LAST_NAME)
       WHEN MATCHED THEN
         UPDATE SET A.FIRST_NAME= B.FIRST_NAME,
                    A.LAST_NAME= B.LAST_NAME;
    
       SELECT CaptureId.GetId INTO :myOutputId FROM DUAL;
    END;
    

    它“给出了一个错误”,因为。然而,如果你想根据定义返回PK,你必须将它返回到某个东西中,这意味着你正在使用某种描述的包装器。这个包装器作为PL/SQL块有什么问题。如果你不想让它成为一个过程/函数,你必须指定你想要使用什么,否则就不可能很好地回答这个问题。作为输出参数传递给此查询的:empId。是否可以从单个合并查询中获取输出参数值?您可能有兴趣阅读此内容-此方法还有另一个问题。如果在ON语句中使用除员工ID以外的限定符(例如
    a.EMPLOYEE\u ID=B.EMPLOYEE\u ID或a.LAST\u NAME=B.LAST\u NAME
    ),则无法捕获ID。使用该限定符,可以为
    员工ID
    传递
    NULL
    ,并在
    姓氏
    上进行匹配。如果
    EMPLOYEE\u ID
    没有找到它,它将无法捕获与
    姓氏匹配的
    EMPLOYEE\u ID