PL/SQL in MariaDB: Lost in translation?

Lost_in_Translation

Generell ist das MySQL-Universum in der letzten Zeit unübersichtlich geworden. Die unterschiedlichen Forks (Oracle, MariaDB, Percona, ...) entwickeln sich teilweise in verschiedene Richtungen bzw. positionieren sich heterogen im Markt. MariaDB bemüht sich dabei auch offensichtlich um die klassischen Oracle-Datenbank-Kunden. Mit der Version MariaDB 10.3 wurde unter anderem ein Subset der Sprache PL/SQL implementiert.

Im Folgenden soll kurz in einer Art Selbstversuch gezeigt werden, welche Schritte notwendig sind, um PL/SQL-Code in einer MariaDB (hier schon in der Version 10.4.11) zu nutzen.

Let's talk PL/SQL

Nach der Installation einer MariaDB (z.B. über fertige Docker Images (https://hub.docker.com/_/mariadb) muss die Datenbank für die Verwendung von PL/SQL konfiguriert werden:
MariaDB> set global sql_mode='ORACLE'; 
Ab diesem Moment ist die Verwendung von PL/SQL-Code in MariaDB möglich.

Was liegt näher als dies zu testen? Im Folgenden werden wird für ein paar kleinere Demonstrationen das wohlbekannte Oracle Beispielschema "hr" benutzten. Unter anderem nutzen wir die Tabellen "EMPLOYEE" und "JOB_HISTORY". Diese enthalten Mitarbeiterdaten (Name, Gehalt, Jobtitel usw.), bzw. die Job-Historie von einzelnen Mitarbeitern.
MariaDB [HR]> DELIMITER /
MariaDB [HR]>
MariaDB [HR]> CREATE OR REPLACE PROCEDURE do_something (E_ID in number, v_return out varchar) AS
    ->   BEGIN
    ->     SELECT 'The salary of EMP# ' || E_ID || ' is:' || SALARY INTO v_return FROM EMPLOYEES;
    ->   END do_something;
    -> /
Query OK, 0 rows affected (0.016 sec) 
MariaDB [HR]> DELIMITER ;
 
Der oben stehende Code ist ein kleiner (sinnfreier) Block Oracle-PL/SQL-Code, der uns eine Textnachricht mit dem Gehalt für einen Mitarbeiter generiert. Er ließ sich problemlos in die MariaDB einspielen und kompilieren.
MariaDB [HR]> call do_something(1, @val);
Query OK, 1 row affected (0.001 sec)
 
Auch der Aufruf der Prozedur ist problemfrei und der Rückgabewert der Prozedur wird in der Variablen @val zurückgeliefert.
MariaDB [HR]> select @val;
+----------------------------------+
| @val                             |
+----------------------------------+
| The salary of EMP# 1 is:20000.00 |
+----------------------------------+
1 row in set (0.000 sec)
 

Translate this!

Von diesem Ergebnis motiviert wagen wir den nächsten Schritt. Nun sollen Elemente des Schemas "hr" aus einer Oracle 19 Datenbank in die MariaDB migriert werden:

  • sieben Tabellen
  • eine View
  • zwei Prozeduren
  • drei Sequenzen

Hierzu wird das Werkzeug Amazon SCT (Schema Conversion Tool) eingesetzt. Dies erlaubt unter anderem die Migration der Strukturen (nicht der Daten!) von einer Oracle DB in eine MariaDB. Andere Konstellationen (inkl. MySQL, PostgreSQL,...) sind auch realisierbar (Details unter: https://aws.amazon.com/de/dms/schema-conversion-tool/).

Die Objekte werden mit Originalnamen und -schreibweise (case-sensitive) auf der MariaDB erzeugt. In unserem Fall sind daher alle Objektnamen in Großbuchstaben erstellt worden. Dies kann aber auf Seiten der MariaDB z.B. über den Parameter (lower_case_table_names) in der Anwendung korrigiert werden.

Nach wenigen Sekunden ist das Datenmodell übertragen. Trotzdem sollte man das Ergebnis kontrollieren:

MariaDB [information_schema]> select table_name, table_type from information_schema.tables where table_schema = 'HR' order by 2,1;
+------------------+------------+
| table_name       | table_type |
+------------------+------------+
| COUNTRIES        | BASE TABLE |
| DEPARTMENTS      | BASE TABLE |
| EMPLOYEES        | BASE TABLE |
| JOBS             | BASE TABLE |
| JOB_HISTORY      | BASE TABLE |
| LOCATIONS        | BASE TABLE |
| REGIONS          | BASE TABLE |
| DEPARTMENTS_SEQ  | SEQUENCE   |
| EMPLOYEES_SEQ    | SEQUENCE   |
| LOCATIONS_SEQ    | SEQUENCE   |
| EMP_DETAILS_VIEW | VIEW       |
+------------------+------------+
11 rows in set (0.001 sec)
 
Alle Tabellen, Views und Sequenzen wurden erfolgreich migriert. Doch was ist mit den Prozeduren?
MariaDB [information_schema]> select routine_name, routine_type from information_schema.routines where routine_schema = 'HR';
+-----------------+--------------+
| routine_name    | routine_type |
+-----------------+--------------+
| ADD_JOB_HISTORY | PROCEDURE    |
| SECURE_DML      | PROCEDURE    |
+-----------------+--------------+
2 rows in set (0.001 sec) 
Auch hier ist also alles im grünen Bereich.

PL/SQL for runaways?

Zeit für einen kleinen Test. Dazu müssen zunächst aber noch ein paar Daten angelegt werden. Wie bereits erwähnt, wurden ja nur die Strukturen (also z.B. leere Tabellen) und nicht die Daten konvertiert.
MariaDB [HR]> select * from EMPLOYEES;
Empty set (0.001 sec)


MariaDB [HR]> select * from JOB_HISTORY;
Empty set (0.003 sec)

MariaDB [HR]> insert into EMPLOYEES values ( 1 , 'Matthias', 'Jung', Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein!', '0611 - 778xxxx', now(), 1, 25000, null, null, null);
Query OK, 1 row affected (0.005 sec)

MariaDB [HR]> select * from EMPLOYEES;
+-------------+------------+-----------+-----------------+----------------+---------------------+--------+----------+----------------+------------+---------------+
| EMPLOYEE_ID | FIRST_NAME | LAST_NAME | EMAIL           | PHONE_NUMBER   | HIRE_DATE           | JOB_ID | SALARY   | COMMISSION_PCT | MANAGER_ID | DEPARTMENT_ID |
+-------------+------------+-----------+-----------------+----------------+---------------------+--------+----------+----------------+------------+---------------+
|           1 | Matthias   | Jung      | Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein! | 0611 - 778xxxx | 2020-04-27 12:36:29 | 1      | 25000.00 |           NULL |       NULL |          NULL |
+-------------+------------+-----------+-----------------+----------------+---------------------+--------+----------+----------------+------------+---------------+
1 row in set (0.001 sec)
 
Mittels der Prozedur wird, z.B. im Rahmen einer Beförderung, Versetzung oder Kündigung protokolliert, welcher Mitarbeiter wann welche Position in der Firma innehatte. Der Code der Prozedur ist der folgende (aus den Oracle SQL-Dateien):
PROCEDURE add_job_history
  (  p_emp_id          job_history.employee_id%type
   , p_start_date      job_history.start_date%type
   , p_end_date        job_history.end_date%type
   , p_job_id          job_history.job_id%type
   , p_department_id   job_history.department_id%type
   )
IS
BEGIN
  INSERT INTO job_history (employee_id, start_date, end_date,
                           job_id, department_id)
    VALUES(p_emp_id, p_start_date, p_end_date, p_job_id, p_department_id);
END add_job_history; 
Nun versuchen wir diesen Code aufzurufen, um den Eintrag des Mitarbeiters #1 (Matthias Jung) in die Tabelle "JOB_HISTORY" zu protokollieren. Dazu deklarieren wir uns über ein SQL-Statement die Variablen @ID und @DATE und nutzen diese beim Aufruf der Prozedur:
MariaDB [HR]> select EMPLOYEE_ID, HIRE_DATE into @ID, @DATE from EMPLOYEES where EMPLOYEE_ID = 1;
Query OK, 1 row affected (0.001 sec)

MariaDB [HR]> call ADD_JOB_HISTORY(@ID, @DATE, now(), 1, null);
Query OK, 1 row affected (0.005 sec)

MariaDB [HR]> select * from JOB_HISTORY\G
*************************** 1. row ***************************
  EMPLOYEE_ID: 1
   START_DATE: 2020-04-27 12:36:29
     END_DATE: 2020-04-27 12:41:05
       JOB_ID: 1
DEPARTMENT_ID: NULL
1 row in set (0.002 sec) 
Die Prozedur läuft einwandfrei.

So far, so good ;-)

Hiermit soll unser kleiner Test abgeschlossen sein. Natürlich wird es nicht ohne weiteres problemlos möglich sein, komplexe PL/SQL-Datenbanken/Applikationen einfach auf MariaDB zu portieren. Unter anderem fehlen alle per default ausgelieferten Packages einer Oracle DB (z.B. dbms_output). Aber auch hier gibt es die ersten aktiven Entwickler, die damit beginnen, diese Pakete für MySQL nachzuimplementieren.

Trotzdem ist es spannend zu sehen, dass es Bemühungen gibt, den Wechsel von Oracle in die OpenSource-Welt noch weiter zu vereinfachen.

Weitere Hinweise zu PL/SQL in MariaDB finden Sie unter:
https://mariadb.com/kb/en/sql_modeoracle-from-mariadb-103/

Sollten Sie Fragen zum Thema Datenbank-Migration und/oder zu MySQL (MariaDB) Datenbanken im Allgemeinen haben, dann sprechen Sie uns an.

By accepting you will be accessing a service provided by a third-party external to https://blog.ordix.de/