Oracle:将 CTE 与更新子句一起使用
Oracle: Using CTE with update clause
我可以在 oracle 数据库中使用常见的 table 表达式进行更新吗?
我在尝试此操作时遇到错误 ORA-00928: missing SELECT keyword
:
with average as (SELECT avg(salary) FROM instructor)
update instructor
set salary = case
when salary <= average then salary * 1.05
else salary * 1.03
end
因为 average salary
只是一个 标量值 你可以做
update instructor
set salary = case
when salary <= (select avg(t.salary) from instructor t) then salary * 1.05
else salary * 1.03
end
在那种情况下,Oracle 首先计算平均值(比如说1234.4567
),然后执行更新。
Can I do something like this in oracle database?
好吧,这不是你能不能做的问题。这是关于你是否需要这样做。在您的查询中,我没有看到任何过滤条件。您想更新所有行吗?我认为您的情况不需要 CTE。
什么时候需要CTE,即当你有多次执行子查询的场景时,一个with子句作为子查询分解方法。您使用 WITH 子句来确保子查询执行一次,并且结果集存储为临时 table.
是的,您可以对 UPDATE 语句使用 WITH 子句。
例如,
UPDATE TABLE t
SET t.column1, t.column2 = (SELECT column1, column2 FROM
(
WITH cte AS(
SELECT ... FROM another_table
)
SELECT * FROM cte
)
您可以使用 MERGE 语句 USING WITH 子句。
例如,
SQL> MERGE INTO emp e USING
2 (WITH average AS
3 (SELECT deptno, AVG(sal) avg_sal FROM emp group by deptno)
4 SELECT * FROM average
5 ) u
6 ON (e.deptno = u.deptno)
7 WHEN MATCHED THEN
8 UPDATE SET e.sal =
9 CASE
10 WHEN e.sal <= u.avg_sal
11 THEN e.sal * 1.05
12 ELSE e.sal * 1.03
13 END
14 /
14 rows merged.
SQL>
基于 another answer 键保留视图的相关更新,这里是在 Oracle SQL 中使用 CTE 更新的另一种可能选项,避免了 where 子句的重复:
update (
with cte as (select avg(salary) average_salary from instructor)
select id, salary, cte.average_salary from instructor cross join cte
where <some_condition>
)
set salary = case
when salary <= average_salary/2 then salary * 1.1
when salary <= average_salary then salary * 1.05
else salary * 1.03
end
在自连接的情况下,这可以简化为无 CTE 版本:
update (
select id, salary, (select avg(salary) from instructor) average_salary
from instructor
where <some_condition>
)
set salary = case
when salary <= average_salary/2 then salary * 1.1
when salary <= average_salary then salary * 1.05
else salary * 1.03
end
我可以在 oracle 数据库中使用常见的 table 表达式进行更新吗?
我在尝试此操作时遇到错误 ORA-00928: missing SELECT keyword
:
with average as (SELECT avg(salary) FROM instructor)
update instructor
set salary = case
when salary <= average then salary * 1.05
else salary * 1.03
end
因为 average salary
只是一个 标量值 你可以做
update instructor
set salary = case
when salary <= (select avg(t.salary) from instructor t) then salary * 1.05
else salary * 1.03
end
在那种情况下,Oracle 首先计算平均值(比如说1234.4567
),然后执行更新。
Can I do something like this in oracle database?
好吧,这不是你能不能做的问题。这是关于你是否需要这样做。在您的查询中,我没有看到任何过滤条件。您想更新所有行吗?我认为您的情况不需要 CTE。
什么时候需要CTE,即当你有多次执行子查询的场景时,一个with子句作为子查询分解方法。您使用 WITH 子句来确保子查询执行一次,并且结果集存储为临时 table.
是的,您可以对 UPDATE 语句使用 WITH 子句。
例如,
UPDATE TABLE t
SET t.column1, t.column2 = (SELECT column1, column2 FROM
(
WITH cte AS(
SELECT ... FROM another_table
)
SELECT * FROM cte
)
您可以使用 MERGE 语句 USING WITH 子句。
例如,
SQL> MERGE INTO emp e USING
2 (WITH average AS
3 (SELECT deptno, AVG(sal) avg_sal FROM emp group by deptno)
4 SELECT * FROM average
5 ) u
6 ON (e.deptno = u.deptno)
7 WHEN MATCHED THEN
8 UPDATE SET e.sal =
9 CASE
10 WHEN e.sal <= u.avg_sal
11 THEN e.sal * 1.05
12 ELSE e.sal * 1.03
13 END
14 /
14 rows merged.
SQL>
基于 another answer 键保留视图的相关更新,这里是在 Oracle SQL 中使用 CTE 更新的另一种可能选项,避免了 where 子句的重复:
update (
with cte as (select avg(salary) average_salary from instructor)
select id, salary, cte.average_salary from instructor cross join cte
where <some_condition>
)
set salary = case
when salary <= average_salary/2 then salary * 1.1
when salary <= average_salary then salary * 1.05
else salary * 1.03
end
在自连接的情况下,这可以简化为无 CTE 版本:
update (
select id, salary, (select avg(salary) from instructor) average_salary
from instructor
where <some_condition>
)
set salary = case
when salary <= average_salary/2 then salary * 1.1
when salary <= average_salary then salary * 1.05
else salary * 1.03
end