PL/SQL in MariaDB: 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
MariaDB> set global sql_mode='ORACLE';
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 ;
MariaDB [HR]> call do_something(1, @val); Query OK, 1 row affected (0.001 sec)
MariaDB [HR]> select @val; +----------------------------------+ | @val | +----------------------------------+ | The salary of EMP# 1 is:20000.00 | +----------------------------------+ 1 row in set (0.000 sec)
Translate this! - Oracle 19 in MariaDB migieren
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
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)
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)
PL/SQL for runaways?
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', 'nomail@ordix.de', '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 | nomail@ordix.de | 0611 - 778xxxx | 2020-04-27 12:36:29 | 1 | 25000.00 | NULL | NULL | NULL | +-------------+------------+-----------+-----------------+----------------+---------------------+--------+----------+----------------+------------+---------------+ 1 row in set (0.001 sec)
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;
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)
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/
Seminarempfehlung
Sie haben Interesse an einer Weiterbildung oder Fragen zu diesem Thema? Sprechen Sie uns an oder besuchen Sie einen unserer Kurse aus unserem Seminarshop:
Zu unseren MySQL-Seminaren
Principal Consultant bei ORDIX
Bei Updates im Blog, informieren wir per E-Mail.
Kommentare