如何在单个语句中更新整个列

Posted

技术标签:

【中文标题】如何在单个语句中更新整个列【英文标题】:How to update entire column in a single statement 【发布时间】:2020-04-08 19:18:18 【问题描述】:

普通的HR方案,如何一次请求更新一整列?

我收到此错误:

ORA-01427: 单行子查询返回多于一行

update depts 
set    tot_dept_sal =
       ( select sum(e.salary)
         from   depts d, employees e 
         where  e.department_id = d.department_id
         group by d.department_name );

有一个表DEPTS:

department_id department_name  Tot_dept_sal
------------- ---------------- ------------
10            Administration   null
20            Marketing        null
30            Purchasing       null
40            Human Resources  null
...
270           Payroll          null

和员工:

employee_id   last_name  salary departments_id
------------- ---------- ------ --------------
100           King       24000  90  
101           Kochhar    17000  90  
102           De Haan    17000  90  
103           Hunold     9000   60  
104           Ernst      6000   60  

【问题讨论】:

您需要共享这些表中的一些示例数据以及您尝试更新的内容。您的查询按原样没有多大意义。 欢迎来到 Stack Overflow。为了帮助我们帮助您,请使用Tour 并通读How To Ask,然后edit() 您的问题以及创建a Minimal, Complete, and Verifiable Example for database-related questions 所需的详细信息。 今日提示:切换到现代、明确的JOIN 语法。更容易编写(没有错误),更容易阅读(和维护),并且如果需要更容易转换为外连接! (他们真的在 2020 年教过古老的逗号分隔的隐式连接?!?可怕......) deptsdepartments 应该是同一张桌子吗?如果是这样,为什么要在子查询中第二次引用更新的表?无论哪种方式,您希望目标表和子查询如何关联?说明您的代码发生了什么通常也很有用 - 大概您收到 ORA-01427 错误? 【参考方案1】:

您已经在外部UPDATE 中获得了departments 表,您可以将子查询与外部查询相关联,而不是在子查询中再次加入它:

update departments d
set tot_dept_sal = (
  select sum(e.salary)
  from   employees e 
  where  d.DEPARTMENT_ID=e.DEPARTMENT_ID
  group by d.department_id
);

因此,对于您的示例数据(更新为具有与 departments 表匹配的 employeesdepatment_id 值):

CREATE TABLE departments ( department_id, department_name, Tot_dept_sal ) AS
SELECT  10, 'Administration',  CAST( null AS NUMBER(8,0) ) FROM DUAL UNION ALL
SELECT  20, 'Marketing',       CAST( null AS NUMBER(8,0) ) FROM DUAL UNION ALL
SELECT  30, 'Purchasing',      CAST( null AS NUMBER(8,0) ) FROM DUAL UNION ALL
SELECT  40, 'Human Resources', CAST( null AS NUMBER(8,0) ) FROM DUAL UNION ALL
SELECT 270, 'Payroll',         CAST( null AS NUMBER(8,0) ) FROM DUAL;

CREATE TABLE employees ( employee_id, last_name, salary, department_id ) AS
SELECT 100, 'King',    24000,  10 FROM DUAL UNION ALL   
SELECT 101, 'Kochhar', 17000,  10 FROM DUAL UNION ALL  
SELECT 102, 'De Haan', 17000,  20 FROM DUAL UNION ALL
SELECT 103, 'Hunold',   9000,  20 FROM DUAL UNION ALL
SELECT 104, 'Ernst',    6000, 270 FROM DUAL;

然后在运行UPDATE 语句后:

SELECT * FROM DEPARTMENTS;

输出:

DEPARTMENT_ID |部门名称 | TOT_DEPT_SAL ------------: | :---------------- | ------------: 10 |管理 | 41000 20 |营销 | 26000 30 |采购 | 40 |人力资源 | 270 |工资单| 6000

db小提琴here

【讨论】:

您甚至不需要这里的group by 子句 - 虽然*8-) 无法确定它是否增加了清晰度【参考方案2】:

您可以按如下方式使用 MERGE 语句:

MERGE INTO departments TRG
USING (SELECT department_id, SUM(salary) AS SALARY
         FROM employees
     GROUP BY department_id) SRC
ON (TRG.department_id = SRC.department_id)
WHEN MATCHED THEN UPDATE SET TRG.Tot_dept_sal = SRC.SALARY;

【讨论】:

以上是关于如何在单个语句中更新整个列的主要内容,如果未能解决你的问题,请参考以下文章

如何在单个合并语句中执行多个更新

更新以在单个语句中切换布尔列

如何在 SQL Server 的单个批次中为列添加默认值并使用默认值更新所有行?

如何利用SQL语句查看某一个表全部列或单个列的属性?

如何在 oracle 12c 中使用多个数据更新单个列

如何基于单个单元格值格式化整个列?