Schlagwort-Archive: Database

MySQL: RENAME SCHEMA or DATABASE Workarounds

Leider ist es nicht möglich ein Schema bzw. Datenbank in MySQL mittels eines SQL-Standard-Befehls umzubennen. Hier folgen einige Workarounds:

SQL-Kommando in einer Bash-Schleife

mysql [OPTIONS] old_schema -sNe 'show tables' | 
while read table; 
  do mysql [OPTIONS] -sNe 
    "RENAME TABLE old_schema.$table TO old_schema.$table"; 
  done

mysqldump

mysqldump [OPTIONS] --database oldSchema > oldSchema.sql
mysql new_schema < oldSchema.sql

ein SQL-Kommando bauen

SET SESSION group_concat_max_len = 4294967295;

SELECT 
    CONCAT(
      'RENAME TABLE ', 
      GROUP_CONCAT( 
        table_schema,'.',table_name, ' TO ','new_schema.',table_name,' '
      ),
      ';'
    ) as stmt 
  FROM information_schema.TABLES 
  WHERE table_schema LIKE 'oldSchema' 
  GROUP BY table_schema;

Welche Alternative man jetzt nimmt, ist zum einen Geschmacksache und zum Anderen hängt es von der Datenbank ab, z.B. ist sie Groß, steht sie unter Dampf etc.

PostgreSQL: Passwort MD5 ermitteln

Immer mal wieder geschieht es, dass ich den PostgreSQL MD5 Hash im Vorfeld ermitteln möchte, z.B. in SQL-Skripten, die Datenbankbenutzer anlegen und ich das Passwort nicht im Klartext ablegen möchte.

Nach ein wenig Recherche und ausprobieren, ist folgendes Bash-Kommando entstanden, um den Hash für das PostgreSQL-Passwort zu generieren.

echo "md5$(echo -n 'PasswordUser' | md5sum )" | tr -d "-"


# Beispiel
# user: Thomas
# pwd: 123

echo "md5$(echo -n '123Thomas' | md5sum )" | tr -d "-"

# Ausgabe: md5b5a51046812abff6595fc57b4e8adb4f

Dies Kommando erspart ab sofort den umständlichen Weg, den Benutzer mit CREATE USER … PASSWORD ‚…‘ anzulegen und dann in der Tabelle pg_catalog.pg_shadow nachzuschauen, wie der MD5 Hash vom vergebenen Passwort ist.

Teste die Datenbank!

Testautomatisierung, Test Driven Development und andere Buzzwords rund ums Testen sind bereits in der Software Entwicklung seit mehreren Jahren keine Neuigkeiten mehr. Dennoch werden Tests auf der Datenbank meist stiefmütterlich behandelt, obwohl die Datenbank ein wichtige zentrale Rolle in der gesamten Applikationslandschaft hat. Um Datenbankfunktionalitäten zu testen, begegnen mir oft gewaltige applikationsseitige Integrationstest, die beim Continuous Integration Prozess sehr lange dauern können. Wäre es nicht schön Datenbankänderungen schneller zu testen? Mit jeder Programmiersprache können einfache und schnelle Unit Tests geschrieben werden. Warum soll das bei SQL anders sein?

In diesem Vortrag wird mit Hilfe des pgTAP Frameworks gezeigt, wie verschiedene Datenbankobjekte (Tabellen, Sichten, Funktion, Trigger, Operatoren u.a.) mit einfachen Unit Test direkt und ohne Applikationslogik auf der PostgreSQL schnell getestet werden können. Dabei werden auch Best Practices zur Vorbereitung, Ausführungen und Aufräumen von Testdaten vorgestellt, die ich in den vergangenen Jahren sammeln konnte.

Hier die Slides von meinem Vortrag auf der 2. Swiss PostgreSQL Conference in Rapperswil.

Teste_Die_Datenbank-Thomas_Koch

 

Eine ausführliche Beschreibung zu pgTAP ist auch hier und natürlich auf pgtap.org zu finden.

Problem: Zwei verschiedene IDs in einer Fremdschlüsselspalte

Ich bin heute auf folgendes Problem gestoßen:

In einer ID-Spalte sollte ein Foreign Key Constraint angelegt werden. Dabei wurde festgestellt, dass die IDs aus zwei verschiedenen Tabellen kommen, z.B. Tabellen author und administrator.

Einige werden bestimmt gleich aufschreien: „Wozu zwei Tabellen, wenn Sie sich nur in Ihrer Rolle unterscheiden?“ Die kurze Antwort darauf: „Sie ist bereits seit einigen Jahren da und die ganze Software arbeitet damit schon immer.“ Abgesehen von der Ursache gilt es das Problem zu lösen.

CREATE TABLE author(id BIGINT, name TEXT);
CREATE TABLE administrator(id BIGINT, description TEXT);

INSERT INTO author VALUES (100, 'Rainer');
INSERT INTO adminstrator VALUES (1, '...');

CREATE TABLE tableA (id INT, user_id, description TEXT);

 

1. Möglichkeit: Inheritance

Es wird eine Tabelle user erstellt. Diese Tabelle dient als Elterntabelle für administrator und author.

CREATE TABLE user(id BIGINT PRIMARY KEY);
ALTER TABLE author INHERIT user;
ALTER TABLE administrator INHERIT user;

-- liefert alle user IDs
SELECT * FROM user;

ALTER TABLE tableA 
  ADD CONSTRAINT "fk_tableA#user_id2user#id" 
    FOREIGN KEY (user_id) REFERENCES user(id);

Schön gedacht – aber funktioniert nicht. Der Grund ist in der PostgreSQL Dokumentation beschrieben.

ERROR:  insert or update on table „tableA“ violates foreign key constraint „fk_tableA#user_id2user#id“
DETAIL:  Key (user_id)=(100) is not present in table „user“.

2. Möglichkeit: Selbstdefinierte Trigger

Die Idee ist einfach: In einem Trigger wird geprüft, ob die user_id vorhanden ist oder nicht. Beim Fehler der user_id mit einer RAISE EXCEPTION abgebrochen.

CREATE OR REPLACE FUNCTION tr_user_check()
  RETURNS TRIGGER AS
$BODY$
BEGIN
  IF ((TG_OP = 'INSERT') OR (TG_OP = 'UPDATE')) THEN
    IF NOT EXISTS (SELECT id FROM user WHERE id = NEW.user_id) THEN
      RAISE EXCEPTION 'user_id=% NOT FOUND in user (administrator, author)', NEW.user_id;
    END IF;
  END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;
CREATE TRIGGER trIU_tableA_user_id_check
BEFORE INSERT OR UPDATE
ON tableA
FOR EACH ROW
EXECUTE PROCEDURE tr_user_check();

INSERT INTO tableA (user_id) VALUES (113); -- error user not exists
INSERT INTO tableA (user_id) VALUES (114); -- yes user exists

Auf ähnliche Weise noch ein DELETE/UPDATE-Trigger auf die Tabellen author, administrator sowie user definiert, der das Ändern der IDs verhindert (Constraint attribute ON UPDATE NO ACTION) oder beim Löschen aufräumt (Constraint ON DELETE CASCADE) und schon ist der Constraint-Check selbst implementiert.

3. Möglichkeit: Table Refactoring

Natürlich bleibt auch immer die Möglichkeit. Eine Tabelle user anlegen, die eine Spalte role (mit den Werten: author, adminstrator) besitzt und die Daten aus den Tabellen author und administrator migrieren. Natürlich stellt sich hier die Frage, wie man mit dem Problem umgeht, wenn die Attribute beide Tabellen zu unterschiedlich sind. Aber auch dafür gibt es mehrere Lösungen.

Skript zum Säubern

Wer die Kommandos mal ausgeführt hat, um selber mal rumzuspielen hier die Befehle zum Säubern.

DELETE FROM tableA WHERE user_id IN (111,113);
DROP TRIGGER trIU_tableA_user_id_check ON tableA;
DROP FUNCTION tr_user_check();
ALTER TABLE author NO INHERIT user;
ALTER TABLE administrator NO INHERIT user;
DROP TABLE user;
DROP TABLE author;
DROP TABLE adminstrator;

 

„How and When to Write SQL in PL/SQL“ – Steven Feuerstein

Ein interessanter Beitrag von Oracle’s PL/SQL Evangelist Steven Feuerstein auf der Oracle Learning Library Platform

Die gemachten Aussagen gelten nicht nur für Oracle, sondern für jedes RDBMS:

  • „SQL statements directly reflect our business models“
  • „You should do as much as possible in pure SQL“
  • „Don’t put the SQL statements in Java or […] Fight the good fight!“
    • „hide complex queries behind views“
    • „put your other SQL statements in PL/SQL packages […], hiding the SQL behind an API of procedures and fucntions“
  • „Set standards for writing SQL in your applications!“

 

 

 

Hauptspeicherdatenbanken – Eine Übersicht

Prof. Dr. habil. Alexander Löser gibt auf golem.de einen kurzen Überblick über den aktuellen Stand von Main-Memory-Database-Management-Systeme (MMDBMS) – auch In-Memory-Datenbanken genannt.
Der Artikel gibt eine Zusammenfassung bzw. Gegenüberstellung von den verschiedenen Speicherarchitekturen, Fail-Over-Szenarien, Kompressionsverfahren, Indexstrukturen. Des Weiteren wird er ergänzt durch einige Einsatzgebiete von MMDBMS.
Neben den bekanntesten Datenbanken wie SAP Hana, Oracle 12c, Microsoft Hekaton werden auch eher noch unbekannte Systeme wie EXASolution, Parstream, MemSQL u.a. benannt. Gerade aber EXASolution ist einer der schnellsten Hauptspeicherdatenbanken, wie auch der TPC-H Benchmark seit Jahren beweist.

Artikel: www.golem.de: data-management-wie-hauptspeicherdatenbanken-arbeiten.html