Schnelle Anonymisierung in DB-Tabellen

Aufgabenstellung ist es, mölichst schnell und unkompliziert eine Tabelle mit typischen Benutzerdaten (z.B. Vor- und Nachname, Geburtsdatum) zu anonymisieren. Aufgrund der Größe der Tabelle mit ca. 35.000 Einträgen erachten wir es als ausreichend, die jeweiligen Spalten „durcheinanderzuwürfeln“, so dass andere Kombinationen aus Vor- und Nachnamen entstehen als in der Ausgangstabelle. Und am besten sollten keine externen Tools verwendet werden, also kein Perl, Java etc.

Ausgangstabelle:

1 Firstname1 Lastname1
2 Firstname2 Lastname2
3 Firstname3 Lastname3

Wir generieren zunächst 3 temporäre Tabellen, in die jeweils ein Attribut gespeichert wird:

CREATE TABLE id_temp
(
id serial NOT NULL,
source_id integer
);

CREATE TABLE firstname_temp
(
id serial NOT NULL,
firstname character varying(70)
);

CREATE TABLE lastname_temp
(
id serial NOT NULL,
lastname character varying(70)
);

und eine Zieltabelle mit derselben Strunktur wie die Ausgangstabelle:

CREATE TABLE shuffeled
(
id integer NOT NULL,
firstname character varying(70),
lastname character varying(70)
);

Dann speichern wir in die temporären Tabellen Werte aus der Ausgangstabelle und nutzen dabei die SQL-Random()-Funktion. Wichtig ist auch das Serial-Feld in den temporären Tabellen, das eine Nummerierung der Zeilen sicherstellt.

INSERT INTO id_temp(source_id) SELECT id from original ORDER BY RANDOM();
INSERT INTO firstname_temp(firstname) SELECT firstname from original ORDER BY RANDOM();
INSERT INTO lastname_temp(lastname) SELECT lastname from original ORDER BY RANDOM();

Das Resultat sind drei Tabellen, die zufällig angeordnete Abfolgen der Spalteninhalte der Ausgangstabelle beinhalten.

id_temp:

id source_id
1 2
2 1
3 3

firstname_temp:

id firstname
1 firstname3
2 firstname2
3 firstname1

lastname_temp:

id lastname
1 firstname2
2 lastname1
3 lastname3

Und als letzer Schritt werden diese zusammengeführt in die Zieltabelle:

INSERT INTO shuffeled (id, firstname, lastname)
SELECT id_temp.source_id AS id,
firstname_temp.firstname AS firstname,
lastname_temp.lastname AS lastname
FROM id_temp, firstname_temp, lastname_temp
WHERE id_temp.id=firstname_temp.id
AND id_temp.id=lastname_temp.id;

Et voila, wir erhalten eine Tabelle mit zufällig angeordneten Kombinationen:

1 Firstname2 Lastname3
2 Firstname3 Lastname1
3 Firstname1 Lastname2

Danach müssen nur noch die temporären Tabellen wieder entfernt werden. Statt in eine Zieltabelle sch schreiben, kann natürlich auch die Ausgangstabelle beschrieben werden.

In der tatsächlichen Anwendung – die noch einiges komplexer ist und ca. 36.000 Einträge hat – dauert das ganze auf einem Standard-PC ca. 6 Sekunden!