Sonntag, April 17, 2011

SCD2-Änderung in einem SQL-Statement


Zu den Dingen, die ich mit SQL (d.h. mit einem einzelnen Statement) bisher nicht geschafft habe, gehört die Aktualisierung von SCD2-Tabellen mit Statusangabe und Änderungsdatum. Für alle, die die Details gerade nicht parat haben, aber trotzdem weiterlesen wollen: http://de.wikipedia.org/wiki/Slowly_Changing_Dimensions.

In Oracle und MS SQL (und auch in anderen SQL-Dialekten) kann man über das MERGE-Statement UPDATE- und INSERT-Operationen kombinieren: wenn ein entsprechender Satz in der (im USING definierten) Referenzquery existiert (WHEN MATCHED), wird die Basistabelle via update aktualisiert (oder es wird via delete aus ihr gelöscht), wenn nicht (WHEN NOT MATCHED), dann wird ein neuer Satz eingefügt. Was dabei aber (zumindest soweit ich es verstanden habe) nicht funktioniert, ist die Kombination von INSERT und UPDATE im „WHEN MATCHED“-Fall; man kann also nicht einen neuen Satz einfügen UND zugleich die Gültigkeitsangaben eines bestehenden Satzes ändern (Status auf inaktiv; Ende der Gültigkeit auf aktuelles Datum). Um eine SCD2 komplett zu aktualisieren, müsste man auf diesem Weg also anschließend ein zweites Update-Statement verwenden, um die Gültigkeit zu korrigieren.

Für den SQL Server 2008 gibt es aber eine Möglichkeit, die mir bisher entgangen war, und die hier beschrieben wird: http://sqlblogcasts.com/blogs/atulthakor/archive/2011/01/10/t-sql-scd-slowly-changing-dimension-type-2-using-a-merge-statement.aspx. Dabei wird das MERGE-Statement als INLINE-View für ein darauf aufbauendes INSERT verwendet – eine Syntax, die ein wenig gewöhnungsbedürftig, aber durchaus nachvollziehbar ist. Voraussetzung sind die MERGE-Erweiterungen von Microsoft, die die Definition einer OUTPUT-clause mit einer Action-Angabe erlauben.

Für Oracle scheint es derzeit keine ähnlich elegante Lösung zu geben, aber unter http://www.business-intelligence-quotient.com/?p=66 findet man einen Workaround (man könnte auch sagen: einen dreckigen Hack), um das Problem durch Verdopplung der Referenzdaten anzugehen (man erzeugt in der Referenz zu jedem Datensatz ein nahezu identisches Duplikat: einen Satz für das INSERT und einen für das UPDATE), was allerdings nur unter bestimmten Voraussetzungen funktioniert. Im Oracle-Fall bleibe ich deshalb lieber bei einer mehrschrittigen Variante.

Keine Kommentare:

Kommentar veröffentlichen