===== Oracle SQL - Update und Merge mit Daten in einer Tabelle mit Werten aus einer zweiten Tabelle =====
**Aufgabe:** Daten in einer Tabelle mit Daten aus einer zweiten Tabelle aktualisieren.
{{:images:highland_kuh_dolomiten_2016.png?300 |Highland Kuh in Oberegen in den Dolomiten - hat wohl andere Sorgen}}
==== Update Lösung ====
=== Inline View für die SQL 92 Syntax ===
Die einfache INNER JOIN Syntax wird auch mit Oracle 12 nicht unterstützt, daher diese Lösung über eine "Inline View" gewählt:
UPDATE(
select emp.PHONE_NUMBER
, DEPARTMENT_ID
from EMPLOYEES emp inner join departments dept using (DEPARTMENT_ID)
where dept.DEPARTMENT_NAME='IT'
)
SET PHONE_NUMBER = '0890000'||to_char(DEPARTMENT_ID)
/
Alternativ traditionell:
UPDATE EMPLOYEES emp
set PHONE_NUMBER = '0890000'|| ( select to_char(dept.DEPARTMENT_ID)
from departments dept
where dept.DEPARTMENT_NAME= 'IT'
and dept.DEPARTMENT_ID = emp.DEPARTMENT_ID )
where emp.DEPARTMENT_ID in ( select DEPARTMENT_ID from departments dept where dept.DEPARTMENT_NAME='IT')
/
Es lassen sich auch mehrere Spalten auf einmal updaten:
UPDATE EMPLOYEES emp
set (PHONE_NUMBER , EMAIL) = ( select '0890000'||to_char(dept.DEPARTMENT_ID),dept.DEPARTMENT_NAME||'@info.de'
from departments dept
where dept.DEPARTMENT_NAME= 'IT'
and dept.DEPARTMENT_ID = emp.DEPARTMENT_ID )
where emp.DEPARTMENT_ID in ( select DEPARTMENT_ID from departments dept where dept.DEPARTMENT_NAME='IT')
/
Wenn das zu langsam wird hift dann nur noch PL/SQL
declare
cursor c_old_id is
select ed.LOCALID,per.per_id_1
from event_detail ed
inner join ods.person per on (per.per_id_3= ed.LOCALID);
v_count pls_integer:=0;
begin
for rec in c_old_id
loop
update event_detail set LOCALID=rec.per_id_1 where LOCALID=rec.LOCALID;
dbms_output.put_line('Set '||rec.LOCALID||' to '||rec.per_id_1);
v_count:=v_count+1;
end loop;
dbms_output.put_line('Update '||v_count||' Records');
end;
/
----
==== Merge Lösung ====
An einfachsten und am besten lesbar ist die Verwendung des Merge Befehles:
MERGE INTO EMPLOYEES emp
USING departments dept
ON (dept.DEPARTMENT_ID = emp.DEPARTMENT_ID and dept.DEPARTMENT_NAME= 'IT' )
WHEN MATCHED THEN
UPDATE SET emp.PHONE_NUMBER = '0890000'||to_char(dept.DEPARTMENT_ID)
/
Alternativ mit SQL Abfrage in den Using Clause:
MERGE INTO EMPLOYEES emp
USING ( select * from departments where DEPARTMENT_NAME= 'IT') dept
ON (dept.DEPARTMENT_ID = emp.DEPARTMENT_ID )
WHEN MATCHED THEN
UPDATE SET emp.PHONE_NUMBER = '0890000'||to_char(dept.DEPARTMENT_ID)
/
**Einschränkung! => ORA-38104: Columns referenced in the ON Clause cannot be updated:**
----
==== Quellen ====
Update:
* https://docs.oracle.com/database/121/SQLRF/statements_10008.htm#SQLRF01708
Merge:
* https://docs.oracle.com/database/121/SQLRF/statements_9016.htm#SQLRF01606