Architektur, Code, Datenbank

Upsert – Datenbank-Einträge erstellen oder aktualisieren mit MERGE

26 October 2007 Keine Kommentare

Erst kürzlich bekam ich die Frage gestellt, wie man einen Datenbank-Eintrag erstellen kann, ohne zu wissen ob dieser Eintrag existiert oder nicht. Konkret handelt es sich hierbei um ein klassisches UPSERT, also ein INSERT-Statement falls der Eintrag nicht existiert oder ein UPDATE-Statement falls der Eintrag existiert. Für die meisten Datenbanken gibt es dafür das MERGE-Statement (übrigens SQL:2003-Standard).

Das eigentlich interessante bei dem UPSERT-Verfahren ist das Anwendungsgebiet. Ich persönlich verwende es oft bei Tabellen, die außer dem Primär- bzw. Surrogatschlüssel noch einen weiteren eindeutigen Schlüssel (Unique Key) hat. Dort ist der Einsatz meiner Meinung nach besonders elegant. Ein kleines Beispiel (mit Oracle):

CREATE TABLE USERS (ID NUMBER(10) PRIMARY KEY, USERNAME VARCHAR2(50) NOT NULL, DESCRIPTION VARCHAR2(50));
CREATE SEQUENCE USERS_SEQ START WITH 1 NOCYCLE;
INSERT INTO USERS VALUES (USERS_SEQ.NEXTVAL, 'JohnDoe', 'Johnny be good.');

Sollte man jetzt sicherstellen, dass der Eintrag für JohnDoe mit der Beschreibung “Johnny is the best.” in der Tabelle eingetragen ist, kann das folgende Merge-Statement verwendet werden:

MERGE INTO USERS USING
(
SELECT 'JohnDoe' NEW_USERNAME, 'Johnny is the best.' NEW_DESCRIPTION FROM DUAL
)
ON
(
USERNAME = NEW_USERNAME
)
WHEN MATCHED THEN
UPDATE SET DESCRIPTION = NEW_DESCRIPTION
WHEN NOT MATCHED THEN
INSERT VALUES (USERS_SEQ.NEXTVAL, NEW_USERNAME, NEW_DESCRIPTION);

Das Ganze funktioniert natürlich auch auf Basis des surrogate primary keys. Das Beispiel mag etwas weit hergeholt wirken, es kommt aber dennoch oft genug in der Praxis vor.

Äußerst interessant wird es meiner Meinung nach allerdings, wenn man genau dasselbe Prinzip zum Beispiel generell für die Save()-Methode eines Active Records verwendet. Man braucht sich nicht mehr darum zu kümmern, ob das Objekt nun tatsächlich in der Datenbank existiert oder nicht. Stattdessen wird einfach das MERGE-Statement abgesetzt und fertig. Dieser Ansatz ist vor allem für verteilte Anwendungen besonders sinnvoll. Ich persönlich habe es in der beschriebenen Art und Form noch nicht eingesetzt, habe allerdings bis dato nur Gutes darüber gehört. Ich bin wie immer gespannt auf eure Meinungen. :-)

Ihre Meinung ist gefragt!

Sie können folgende Tags verwenden:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Dieser Blogs unterstützt Gravatare.
Falls Sie noch keines haben, können Sie Ihren persönlichen Avatar bei Gravatar erstellen.