Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CTE and table update in ORACLE

I have a lot of complicated logic I want to run before I finally store the result by updating a column in a table. I am getting an error and have been able to get it down to:

with my_cte as
(
  select x,ix from y
)
update z
set mycol = (select x from my_cte where z.ix = my_cte.ix)

This however gives the error:

Error at line 4:
ORA-00928: missing SELECT keyword
set mycol = (select x from my_cte where z.ix = my_cte.ix)

Does this simply mean CTEs cannot be used with updates since the following query works fine:

update z
set mycol = (select x from y where y.ix = my_cte.ix)

Using version 12c Enterprise Edition Release 12.1.0.2.0

Edit:

After tackling this problem for a while the only way to get a reasonable performance was to use the MERGE clause instead (Still using CTEs as in the answers below).

merge into z using (
  with my_cte as (
    select x,ix from y
  )
)
on (
  my_cte.ix = z.ix 
)
when matched then
update set mycol = my_cte.x
like image 731
hirolau Avatar asked Oct 31 '16 11:10

hirolau


People also ask

Does updating a CTE update the table?

Updatable CTE If your CTE is based on a single table then you can update using CTE, which in turn updates the underlying table.

Can we use CTE in update statement Oracle?

WITH name as (subselect ) is limited to SELECT as far as I know.... generic sql-l list, but if I remember correctly, you can't use a CTE in an UPDATE statement.

Can CTE be used for update statement?

Specifies a temporary named result set, known as a common table expression (CTE). This is derived from a simple query and defined within the execution scope of a single SELECT, INSERT, UPDATE, DELETE or MERGE statement. This clause can also be used in a CREATE VIEW statement as part of its defining SELECT statement.

What is the use of CTE in Oracle?

A common table expression (CTE) is a named temporary result set that exists within the scope of a single statement and that can be referred to later within that statement, possibly multiple times.


1 Answers

In Oracle, the CTE is part of the SELECT not the UPDATE:

update z
    set mycol = (
          with my_cte as (
             select x, ix
             from y
          )
          select x from my_cte where z.ix = my_cte.ix
         );
like image 190
Gordon Linoff Avatar answered Oct 01 '22 09:10

Gordon Linoff