Stored Procedure mit User-defined Types unter PostgreSQL
In diesem Beitrag möchte ich zeigen, wie eine Stored Procedure mit User-defined Types (UDT) in einer PostgreSQL Datenbank programmiert wird. Im übergeordneten Beitrag Spring und Stored Procedure mit User-defined Types wird das Aufrufen dieser Stored Procedure aus Java heraus gezeigt. Im Beitrag Stored Procedure mit User-defined Types unter Oracle wird dieses Beispiel anhand einer Oracle Database beschrieben.
Dieser Beitrag beschreibt …
- das Installieren eines PostgreSQL Datenbankservers
- das Anlegen einer Datenbank unter PostgreSQL
- das Erzeugen einer Stored Procedure mit User-defined Types (UDT)
Die Installation des PostgreSQL Datenbankservers
Der PostgreSQL Datenbankservers wird unter dem Betriebssystem Ubuntu mit folgenden Befehlen installiert.
$ sudo apt-get install postgresql ... $ sudo service postgresql status Running clusters: 9.1/main
Der Datenbankserver wurde installiert, direkt konfiguriert und gestartet.
Nun wird noch der Datenbankbenutzer dba
eingerichtet. Dazu muss der sudo
Befehl mit der Option -u postgres
ausgeführt werden, da die Instanz der Datenbankservers dem Betriebssystembenutzer postgres
gehört. Die Option -P
sorgt dafür, dass das Passwort abgefragt wird.
$ sudo -u postgres createuser -P dba Enter password for new role: Enter it again: Shall the new role be a superuser? (y/n) y
Das Anlegen einer Datenbank
Dieser Befehl erzeugt die Datenbank TEST_SPRING_JDBC
. Die Option -O dba
legt den Datenbankbenutzer dba
als Eigentümer der Datenbank fest.
$ sudo -u postgres createdb -O dba TEST_SPRING_JDBC "Test Datenbank für test-spring-jdbc"
Dieser Befehl macht die prozedurale Programmiersprache PL/pgSQL
in dieser Datenbank verfügbar.
Mögliche Alternativen: PL/Tcl
, PL/Perl
, PL/Python
, PL/Java
, …
$ sudo -u postgres createlang plpgsql TEST_SPRING_JDBC
Das Erzeugung einer Stored Function per Konsolenanwendung
Als erstes wird über die Konsolenanwendung psql
eine Funktion erzeugt.
$ psql TEST_SPRING_JDBC psql (9.1.7) Type "help" for help. TEST_SPRING_JDBC=#
Die Eingabe des SQL Befehls zur Erzeugung der Funktion fn_info()
.
TEST_SPRING_JDBC=# CREATE OR REPLACE FUNCTION fn_info() RETURNS text AS $ TEST_SPRING_JDBC$# BEGIN TEST_SPRING_JDBC$# RETURN 'Eine einfache Funktion'; TEST_SPRING_JDBC$# END; TEST_SPRING_JDBC$# $ LANGUAGE plpgsql; CREATE FUNCTION TEST_SPRING_JDBC=#
Mit dem folgenden SQL Befehl wird die gerade erzeugte Funktion getestet.
TEST_SPRING_JDBC=# SELECT fn_info(); fn_info ------------------------ Eine einfache Funktion (1 row) TEST_SPRING_JDBC=#
Die Anzeigen der erzeugten Funktionen.
TEST_SPRING_JDBC=# df List of functions Schema | Name | Result data type | Argument data types | Type --------+---------------+------------------+--------------------------------------------------------+-------- public | fn_info | text | | normal (1 rows) TEST_SPRING_JDBC=#
Das Erzeugung der Stored Procedure mit User-defined Types
Mit dem folgendem Skript wird die Stored Procedure und die User-defined Types angelegt.
Zunächst werden aber die existierenden Prozeduren bzw. Typen kaskadierend gelöscht.
DROP FUNCTION IF EXISTS searchPersons( INTEGER, s_User ) CASCADE; DROP DOMAIN IF EXISTS a_Person CASCADE; DROP TYPE IF EXISTS s_User CASCADE; DROP TYPE IF EXISTS s_Person CASCADE;
In den folgenden Zeilen werden die benutzerdefinierten Typen des aktuellen Benutzers und einer Person angelegt.
CREATE TYPE s_User AS ( -- Der aktuelle Benutzer id CHAR(10), name VARCHAR(30), dept VARCHAR ); CREATE TYPE s_Person AS ( -- Eine Person id BIGINT, name VARCHAR(30), salary DECIMAL, dateOfBirth DATE );
_s_Person
für s_Person[]
und _s_User
für s_User[]
).
Da andere Datenbanken diese Konzept nicht kennen, werden hier benutzerdefinierte Wertebereiche (DOMAIN
) verwendet.
CREATE DOMAIN a_Person AS s_Person[]; -- Collection der Person
In folgenden Zeilen wird die eigentliche Stored Procedure erzeugt.
- In den Zeilen 24 und 25 sind die Eingabeparameter der Prozedur definiert.
- In der Zeile 26 ist der Rückgabeparameter als ein Liste von Personen definiert.
- In den Zeilen 29 bis 32 sind die Variablen dieser Prozedur definiert.
- In der Zeile 32 wird das Geburtsdatum mit dem aktuellen Datum vorbelegt.
- In der Zeile 34 wird eine Meldung auf die Kommandozeile geschrieben.
- In der Zeile 38 wird eine neue Person angelegt.
- In der Zeile 42 wird die konstant Kreiszahl Pi (π) verwendet, um ein Gehalt auszurechnen.
- In der Zeile 43 wird die veränderte Person zurück in das Array gestellt.
CREATE FUNCTION searchPersons( -- Suche Personen p_num IN INTEGER, p_user IN s_User, p_persons OUT a_Person ) AS $BODY$ -- Beginn der PL/pgSQL Funktion DECLARE -- Deklarationsblock i INTEGER; p s_Person; dateOfBirth DATE := current_date; BEGIN -- Ausführungsteil RAISE NOTICE 'Die Stored Procedure searchPersons wurde aufgerufen. User=%', p_user; FOR i IN 1..p_num LOOP -- Fake der Suche p := p_persons[i]; p.id := i; p.name := p_user.name; p.dateOfBirth := dateOfBirth; p.salary := pi() * i * 100; p_persons[i] := p; END LOOP; END; $BODY$ -- Ende der Funktion LANGUAGE plpgsql; -- Die Sprache des Funktionskörpers
Die Ausführung dieses Skriptes mit dem Kommando psql
liefert folgende Konsolenausgaben.
$ psql --file=src/sql/postgresql/init.sql TEST_SPRING_JDBC psql:src/sql/postgresql/init.sql:3: NOTICE: function searchpersons() does not exist, skipping DROP FUNCTION psql:src/sql/postgresql/init.sql:4: NOTICE: type "a_person" does not exist, skipping DROP DOMAIN psql:src/sql/postgresql/init.sql:5: NOTICE: type "s_user" does not exist, skipping DROP TYPE psql:src/sql/postgresql/init.sql:6: NOTICE: type "s_person" does not exist, skipping DROP TYPE CREATE TYPE CREATE TYPE CREATE DOMAIN CREATE FUNCTION
Mit den Kommandos df
und dT+
in der Konsolenanwendung psql
können die Details über die Stored Procedures bzw. UDTs abgefragt werden. Mit dem Kommando q
wird die Konsolenanwendung verlassen.
$ psql TEST_SPRING_JDBC psql (9.1.6) Type "help" for help. TEST_SPRING_JDBC=# df List of functions Schema | Name | Result data type | Argument data types | Type --------+---------------+------------------+------------------------------------------------------+-------- public | fn_info | text | | normal public | searchpersons | a_person | p_num integer, p_user s_user, OUT p_persons a_person | normal (2 row) TEST_SPRING_JDBC=# dT+ List of data types Schema | Name | Internal name | Size | Elements | Description --------+----------+---------------+-------+----------+------------- public | a_person | a_person | var | | public | s_person | s_person | tuple | | public | s_user | s_user | tuple | | (3 rows) TEST_SPRING_JDBC=# q $
Das folgende Skript dient der Überprüfung der angelegten Prozedur.
- In den Zeilen 1 bis 11 wird eine Funktion definiert, die ein Benutzer erzeugt.
CREATE OR REPLACE FUNCTION get_user() RETURNS s_User AS $$ DECLARE u s_User; BEGIN u.id := 4711; u.name := 'Frank Rahn'; u.dept := 'Entwicklung'; RETURN u; END; $$ LANGUAGE plpgsql; SELECT * FROM searchPersons(5, get_user()); DROP FUNCTION IF EXISTS get_user();
Die Konsolenausgabe dieses Skripts zeigt, dass die Stored Procedure aufgerufen wurde.
$ psql --file=src/sql/postgresql/test.sql TEST_SPRING_JDBC CREATE FUNCTION psql:src/sql/postgresql/test.sql:13: NOTICE: Die Stored Procedure searchPersons wurde aufgerufen. User=("4711 ","Frank Rahn",Entwicklung) DROP FUNCTION $
Die folgenden Ausgaben zeigen die Rückgabe der Stored Procedure.
p_persons ---------------------------------------------------------------------------------------------- {"(1,"Frank Rahn",314.159265358979,2012-10-27)","(2,"Frank Rahn",628.318530717959,2012...
- Wer ist der optimale Java Bean Mapper? - Freitag, 22. September 2023
- Spring Boot Webanwendung: Die ersten Schritte (Tutorial) - Montag, 28. März 2016
- Mainframe-Zugriff via Java - Sonntag, 04. Mai 2014
Trackbacks & Pingbacks
[…] User-defined Types wird das Aufrufen dieser Stored Procedure aus Java heraus gezeigt. Im Beitrag Stored Procedure mit User-defined Types unter PostgreSQL wird dieses Beispiel anhand einer PostgreSQL Datenbank […]
Hinterlasse einen Kommentar
An der Diskussion beteiligen?Hinterlasse uns deinen Kommentar!