【问题标题】:How to update a table using inner join如何使用内连接更新表
【发布时间】:2012-02-07 10:46:42
【问题描述】:

我有两张表 Emp & Dept。

SQL> select * from emp where rownum<4;

     EMPNO ENAME      JOB              MGR        SAL     DEPTNO
---------- ---------- --------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902        800
      7499 ALLEN      SALESMAN        7698       1600
      7521 WARD       SALESMAN        7698       1250

SQL> select * from dept;

    DEPTNO DNAME           LOC                  EMPNO
---------- --------------- --------------- ----------
        10 ACCOUNTING      NEW YORK              7369
        20 RESEARCH        DALLAS                7499
        30 SALES           CHICAGO               7521
        40 OPERATIONS      BOSTON

我想更新 emp 的 deptno,它应该与 dept 表的 deptno 相同,其中 dept 的 empno 应该等于 emp 的 empno;简而言之,我想通过 emp 使用内部连接操作来更新部门;

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    在 Oracle 中,执行此操作的规范方法是 MERGE 语句:

    MERGE INTO emp e
    USING dept d
       ON (d.empno = e.empno)
     WHEN MATCHED THEN UPDATE SET e.deptno = d.deptno
    

    但是,如果您使用的是 Oracle 9(见下文),或者您的表上有域索引(例如 Oracle Text),上述方法将不起作用

    asked a question previously 了解 MERGE 语句的作用。

    e 的每一行都必须通过连接条件(ON 部分)连接到无或正好 1 行的d,否则你会得到 ORA-30926 “Unable to get a stable源表中的一组行”。

    未连接到任何部门的e 行保持不变,未连接到任何员工的d 行可用于INSERTS(并且在 Oracle 9 中必须用于WHEN NOT MATCHED THEN INSERT(cols) VALUES(...) 子句;如果您使用的是 Oracle 9,那么此答案不适合您)。

    另一种选择,但受到相同的基本限制:

    UPDATE (SELECT e.deptno edeptno, d.deptno ddeptno
              FROM emp e, dept d
             WHERE e.empno = d.empno)
       SET edeptno = ddeptno
    

    或者

    UPDATE emp
       SET deptno = ( SELECT deptno FROM dept WHERE empno = emp.empno )
     WHERE empno IN ( SELECT empno FROM dept )
    

    如您所见,解决方案众多,但受到限制。

    【讨论】:

    • 那么,您在这三个中选择了哪一个,您更喜欢哪一个?
    【解决方案2】:
    更新员工 set deptno = (从dept d中选择DEPTNO,其中d.empno = e.empno)

    只要 DEPT 中的 EMPNO 是唯一的就可以工作。

    编辑 - 正如所指出的,如果 EMPNO 不存在,这将失败。

    解决这个问题的方法非常 HACKY,

    更新员工

    设置deptno = (

             SELECT RESULT FROM (
              select DEPTNO RESULT from dept d where d.empno = e.empno
               UNION ALL 
               select NULL from DUAL 
               ORDER BY 1
               ) WHERE ROWNUM < 2
             )
    

    【讨论】:

    • 是的。但如果在部门中找不到员工,则会失败。
    • UNION ALL select null from dual order by 1 应该包括NULLS LAST,但更简单的是RIGHT JOIN dual ON 1 = 1
    猜你喜欢
    • 1970-01-01
    • 2019-06-25
    • 2014-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多