diff --git a/20231207/Zeichen_123.pdf b/20231207/Zeichen_123.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..fdbc897227df059cfda790a16555e6e417682116
--- /dev/null
+++ b/20231207/Zeichen_123.pdf
@@ -0,0 +1 @@
+../common/Zeichen_123.pdf
\ No newline at end of file
diff --git a/20231207/dbs-20231207.pdf b/20231207/dbs-20231207.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..0ed5fc0a3320efa5dec3a3c373b1e2c3ed4775fe
Binary files /dev/null and b/20231207/dbs-20231207.pdf differ
diff --git a/20231207/dbs-20231207.tex b/20231207/dbs-20231207.tex
new file mode 100644
index 0000000000000000000000000000000000000000..2296ae2843ec63b2d755855dbfda23f9323fc86b
--- /dev/null
+++ b/20231207/dbs-20231207.tex
@@ -0,0 +1,278 @@
+% dbs-20221207.pdf - Lecture Slides on Databases and Information Security
+% Copyright (C) 2023  Peter Gerwinski
+%
+% This document is free software: you can redistribute it and/or
+% modify it either under the terms of the Creative Commons
+% Attribution-ShareAlike 3.0 License, or under the terms of the
+% GNU General Public License as published by the Free Software
+% Foundation, either version 3 of the License, or (at your option)
+% any later version.
+%
+% This document is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this document.  If not, see <http://www.gnu.org/licenses/>.
+%
+% You should have received a copy of the Creative Commons
+% Attribution-ShareAlike 3.0 Unported License along with this
+% document.  If not, see <http://creativecommons.org/licenses/>.
+
+% README: Funktionen, Trigger, SQL Injection
+
+\documentclass[10pt,t]{beamer}
+
+\usepackage{pgslides}
+
+\newcommand{\vfilll}{\vspace{0pt plus 1filll}}
+
+\newcommand{\underconstruction}{%
+  \begin{picture}(0,0)
+    \put(11,1.2){\makebox(0,0)[b]{\includegraphics[width=1.5cm]{Zeichen_123.pdf}}}
+    \put(11,0.9){\makebox(0,0)[t]{\shortstack{Änderungen\\vorbehalten}}}
+  \end{picture}}
+
+\title{Datenbanken und Datensicherheit}
+\author{Prof.\ Dr.\ rer.\ nat.\ Peter Gerwinski}
+\date{7.\ Dezember 2023}
+
+\begin{document}
+
+\maketitleframe
+
+\nosectionnonumber{\inserttitle}
+
+\begin{frame}
+
+  \shownosectionnonumber
+
+  \begin{itemize}
+    \item[\textbf{1}] \textbf{Einführung}
+      \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/dbs}}}%
+    \item[\textbf{2}] \textbf{Kurzeinführung Unix}
+    \item[\textbf{3}] \textbf{Kurzeinführung TCP/IP}
+    \item[\textbf{4}] \textbf{Relationale Datenbanken}
+      \begin{itemize}
+        \vspace*{-\smallskipamount}
+        \item[\textbf{\dots}]
+        \item[4.7] Datensicherung
+        \color{medgreen}
+        \item[4.8] Transaktionen
+        \item[4.9] Indizierung
+        \color{red}
+        \item[4.10] Funktionen und Trigger
+        \color{orange}
+        \item[4.11] GUI-Zugriff
+        \color{red}
+        \item[4.12] SQL Injection
+        \color{black}
+        \item[4.13] Sonstige Datenbanken
+      \end{itemize}
+    \item[\textbf{5}] \textbf{Kryptographie}
+      \begin{itemize}
+        \item[5.1] Einführung
+        \vspace*{-\smallskipamount}
+        \item[\textbf{\dots}]
+      \end{itemize}
+    \vspace*{-\smallskipamount}
+    \item[\textbf{\dots}]
+  \end{itemize}
+
+  \vfilll
+  \underconstruction
+
+\end{frame}
+
+\setcounter{section}{3}
+\section{Relationale Datenbanken}
+\setcounter{subsection}{7}
+\subsection{Transaktionen}
+
+\begin{frame}[fragile]
+
+  \showsection
+  \showsubsection
+
+  \begin{itemize}
+    \item
+      Ziel: Wahrung der Konsistenz
+    \item
+      Methode: zusammengehörige Aktionen zu einer \newterm{Transaktion} zusammenfassen
+    \item
+      Beispiel: Überweisung\\
+      Betrag von einem Konto subtrahieren\\
+      und "`gleichzeitig"' zu einem anderen Konto addieren
+    \item
+      Realisierung in PostgreSQL:
+      \lstinline[style=cmd]{BEGIN;} \dots\ \lstinline[style=cmd]{COMMIT;}
+    \item
+      Realisierung in MariaDB:
+      \lstinline[style=cmd]{START TRANSACTION;} \dots\ \lstinline[style=cmd]{COMMIT;}
+    \item
+      Abbruch einer Transaktion:
+      \lstinline[style=cmd]{ROLLBACK;} statt \lstinline[style=cmd]{COMMIT;}
+  \end{itemize}
+
+\end{frame}
+
+\subsection{Indizierung}
+
+\begin{frame}[fragile]
+
+  \showsection
+  \showsubsection
+
+  \begin{itemize}
+    \item
+      Ziel: Performanzgewinn
+    \item
+      Methode: Spalten, in denen häufig gesucht wird, sortieren
+    \item
+      Beispiel: Datenbank mit Kontaktdaten\\
+      Suche nach Name, Adresse, Telefonnummer
+    \item
+      Realisierung in PostgreSQL und MariaDB:
+      \begin{lstlisting}[style=cmd,gobble=8]
+        CREATE INDEX <Indexname> ON <Tabellenname>
+        (
+          <Spaltenname>,
+          ...
+        );
+      \end{lstlisting}
+    \item
+      Vorteil: schnellere Suche (\lstinline[style=cmd]{SELECT}) in indizierten Spalten
+%    \pause
+    \item
+      Nachteil: langsameres Einfügen/Ändern/Löschen
+  \end{itemize}
+
+\end{frame}
+
+\subsection{Funktionen und Trigger}
+
+\begin{frame}
+
+  \showsection
+  \showsubsection
+
+  Funktionen:
+  \begin{itemize}
+    \item
+      \lstinline[style=cmd]{PROCEDURE} entspricht einer \lstinline{void}-Funktion in C.
+    \item
+      \url{https://www.postgresql.org/docs/15/sql-createprocedure.html}
+  \end{itemize}
+
+  \bigskip
+
+  Trigger:
+  \begin{itemize}
+    \item
+      \url{https://www.sqltutorial.org/sql-triggers/}
+    \item
+      \url{https://www.postgresqltutorial.com/postgresql-triggers/creating-first-trigger-postgresql/}
+  \end{itemize}
+
+\end{frame}
+
+\subsection{GUI-Zugriff}
+
+\begin{frame}
+
+  \showsection
+  \showsubsection
+
+  \begin{itemize}
+    \item
+      Anwendung nutzt DBMS-Client-Bibliothek\\
+      GUI-Programmierung: wie gewohnt
+    \item
+      Spezialfall: Web-Anwendung
+  \end{itemize}
+
+  \bigskip
+
+  Beispiel: Programmiersprache PHP
+  \begin{itemize}
+    \item
+      Integration in HTML-Quelltext: \lstinline{<?php ... ?>}
+    \item
+      Objekt zur Kommunikation mit Datenbanken: \lstinline{PDO}
+  \end{itemize}
+
+  \bigskip
+
+  Literatur:
+  \begin{itemize}
+    \item
+      \url{https://www.postgresqltutorial.com/postgresql-php/connect/}
+    \item
+      \url{https://www.phptutorial.net/php-pdo/pdo-connecting-to-postgresql/}
+  \end{itemize}
+
+\end{frame}
+
+\subsection{SQL Injection}
+
+\begin{frame}
+
+  \showsection
+  \showsubsection
+
+  Literatur:
+  \begin{itemize}
+    \item
+      \url{https://xkcd.com/327/}
+  \end{itemize}
+
+\end{frame}
+
+\iffalse
+
+\subsection{Sonstige Datenbanken}
+
+\begin{frame}
+
+  \showsection
+  \showsubsection
+
+  \begin{itemize}
+    \item
+      Eingebettete Datenbanken:\\
+      Berkeley DB, SQLite\\
+      Software-Bibliothek, keine Client-Server-Struktur
+    \item
+      Nicht-relationale Datenbanken:\\
+      dokumentenorientierte Datenbanken, noSQL\\
+      Performanz wichtiger als Konsistenz\\
+      \textarrow\ Applikationen stärker in Konsistenzprüfung eingebunden
+  \end{itemize}
+
+\end{frame}
+
+\section{Kryptographie}
+\subsection{Einführung}
+
+\begin{frame}
+
+  \showsection
+  \showsubsection
+
+  \begin{itemize}
+    \item
+      Verschlüsselung: symmetrisch, asymmetrisch, hybrid
+    \item
+      Hashes: Einwegfunktionen, Salt
+    \item
+      Signaturen, Zertifikate
+    \item
+      Schlüsselaustausch
+  \end{itemize}
+
+\end{frame}
+
+\fi
+
+\end{document}
diff --git a/20231207/functions-01.txt b/20231207/functions-01.txt
new file mode 100644
index 0000000000000000000000000000000000000000..bb84b14be75de373bfec371af3d2b9ec84182f7b
--- /dev/null
+++ b/20231207/functions-01.txt
@@ -0,0 +1,154 @@
+testdb=> \d
+               Liste der Relationen
+ Schema |       Name       |   Typ   | Eigentümer
+--------+------------------+---------+------------
+ public | account          | Tabelle | dbs
+ public | account_id_seq   | Sequenz | dbs
+ public | cd               | Tabelle | dbs
+ public | cd_cd_id_seq     | Sequenz | dbs
+ public | customer         | Tabelle | dbs
+ public | customer_id_seq  | Sequenz | dbs
+ public | interpret        | Tabelle | dbs
+ public | interpret_id_seq | Sequenz | dbs
+ public | lied             | Tabelle | dbs
+ public | lied_auf_cd      | Sicht   | dbs
+ public | test             | Tabelle | dbs
+ public | tier             | Tabelle | dbs
+ public | tier_id_seq      | Sequenz | dbs
+(13 Zeilen)
+
+testdb=> \d customer
+                                 Tabelle »public.customer«
+   Spalte   |   Typ   | Sortierfolge | NULL erlaubt? |             Vorgabewert
+------------+---------+--------------+---------------+--------------------------------------
+ id         | integer |              | not null      | nextval('customer_id_seq'::regclass)
+ lastname   | text    |              |               |
+ firstname  | text    |              |               |
+ account_id | integer |              |               |
+Indexe:
+    "customer_pkey" PRIMARY KEY, btree (id)
+Fremdschlüssel-Constraints:
+    "customer_fkey_account_id" FOREIGN KEY (account_id) REFERENCES account(id)
+
+testdb=> \d account
+                                Tabelle »public.account«
+ Spalte  |   Typ   | Sortierfolge | NULL erlaubt? |             Vorgabewert
+---------+---------+--------------+---------------+-------------------------------------
+ id      | integer |              | not null      | nextval('account_id_seq'::regclass)
+ number  | text    |              |               |
+ balance | integer |              |               |
+Indexe:
+    "account_pkey" PRIMARY KEY, btree (id)
+    "index_account_number" btree (number)
+Fremdschlüsselverweise von:
+    TABLE "customer" CONSTRAINT "customer_fkey_account_id" FOREIGN KEY (account_id) REFERENCES account(id)
+
+testdb=> create procedure transfer (sender integer, receiver integer, amount integer) language sql as 'BEGIN; UPDATE account SET balance = balance + amount WHERE id = receiver; UPDATE account SET balance = balance - amount WHERE id = sender; COMMIT;';
+CREATE PROCEDURE
+testdb=> select * from customer;
+ id |  lastname  | firstname | account_id
+----+------------+-----------+------------
+  2 | Mustermann | Erika     |          1
+  4 | Rich       | Richie    |          2
+(2 Zeilen)
+
+testdb=> select * from account;
+ id |           number            | balance
+----+-----------------------------+---------
+  1 | DE12 3456 7890 ABCD EFGH IJ | 1000001
+  2 | DE98 7654 3210 ABCD EFGH IJ | 3999999
+(2 Zeilen)
+
+testdb=> call transfer (2, 4, 1);
+FEHLER:  BEGIN ist in SQL-Funktionen nicht erlaubt
+KONTEXT:  SQL-Funktion »transfer« beim Start
+testdb=> create or replace procedure transfer (sender integer, receiver integer, amount integer) language sql as 'UPDATE account SET balance = balance + amount WHERE id = receiver; UPDATE account SET balance = balance - amount WHERE id = sender;';
+CREATE PROCEDURE
+testdb=> call transfer (2, 4, 1);                                                            CALL                                                                                         testdb=> select * from account;                                                               id |           number            | balance                                                  ----+-----------------------------+---------
+  1 | DE12 3456 7890 ABCD EFGH IJ | 1000001
+  2 | DE98 7654 3210 ABCD EFGH IJ | 3999998
+(2 Zeilen)
+
+testdb=> call transfer (1, 2, 1);
+CALL
+testdb=> select * from account;
+ id |           number            | balance
+----+-----------------------------+---------
+  2 | DE98 7654 3210 ABCD EFGH IJ | 3999999
+  1 | DE12 3456 7890 ABCD EFGH IJ | 1000000
+(2 Zeilen)
+
+testdb=> call transfer (select account_id from customer where lastname = 'Mustermann', select account_id from customer where lastname = 'Rich', 1);
+FEHLER:  Syntaxfehler bei »select«
+ZEILE 1: call transfer (select account_id from customer where lastnam...
+                        ^
+testdb=> call transfer ((select account_id from customer where lastname = 'Mustermann'), (select account_id from customer where lastname = 'Rich'), 1);
+FEHLER:  Unteranfragen können nicht in CALL-Argument verwendet werden
+ZEILE 1: call transfer ((select account_id from customer where lastna...
+                        ^
+testdb=> Query failed: Error: Error(s) encountered during statement execution: no such table: moz_hosts
+Query failed: Error: Error(s) encountered during statement execution: no such table: moz_hosts
+sender integer;
+FEHLER:  Syntaxfehler bei »sender«
+ZEILE 1: sender integer;
+         ^
+testdb=> declare sender integer;
+FEHLER:  Syntaxfehler bei »integer«
+ZEILE 1: declare sender integer;
+                        ^
+testdb=> set var.sender = 1;
+SET
+testdb=> set var.sender = ( select account_id from customer where lastname = 'Mustermann' );
+FEHLER:  Syntaxfehler bei »(«
+ZEILE 1: set var.sender = ( select account_id from customer where las...
+                          ^
+testdb=> var.sender = ( select account_id from customer where lastname = 'Mustermann' );
+FEHLER:  Syntaxfehler bei »var«
+ZEILE 1: var.sender = ( select account_id from customer where lastnam...
+         ^
+testdb=> set var.sender = ( select account_id from customer where lastname = 'Mustermann' );
+FEHLER:  Syntaxfehler bei »(«
+ZEILE 1: set var.sender = ( select account_id from customer where las...
+                          ^
+testdb=> set var.sender = select account_id from customer where lastname = 'Mustermann';
+FEHLER:  Syntaxfehler bei »select«
+ZEILE 1: set var.sender = select account_id from customer where lastn...
+                          ^
+testdb=> DECLARE sender INTEGER;
+FEHLER:  Syntaxfehler bei »INTEGER«
+ZEILE 1: DECLARE sender INTEGER;
+                        ^
+testdb=> select account_id from customer where lastname = 'Mustermann';
+ account_id
+------------
+          1
+(1 Zeile)
+
+testdb=> call transfer (1, 2, 1);                                                            CALL
+testdb=> select * from account;
+ id |           number            | balance
+----+-----------------------------+---------
+  2 | DE98 7654 3210 ABCD EFGH IJ | 4000000
+  1 | DE12 3456 7890 ABCD EFGH IJ |  999999
+(2 Zeilen)
+
+testdb=> \d
+               Liste der Relationen
+ Schema |       Name       |   Typ   | Eigentümer
+--------+------------------+---------+------------
+ public | account          | Tabelle | dbs
+ public | account_id_seq   | Sequenz | dbs
+ public | cd               | Tabelle | dbs
+ public | cd_cd_id_seq     | Sequenz | dbs
+ public | customer         | Tabelle | dbs
+ public | customer_id_seq  | Sequenz | dbs
+ public | interpret        | Tabelle | dbs
+ public | interpret_id_seq | Sequenz | dbs
+ public | lied             | Tabelle | dbs
+ public | lied_auf_cd      | Sicht   | dbs
+ public | test             | Tabelle | dbs
+ public | tier             | Tabelle | dbs
+ public | tier_id_seq      | Sequenz | dbs
+(13 Zeilen)
+
+testdb=>
diff --git a/20231207/logo-hochschule-bochum-cvh-text-v2.pdf b/20231207/logo-hochschule-bochum-cvh-text-v2.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8
--- /dev/null
+++ b/20231207/logo-hochschule-bochum-cvh-text-v2.pdf
@@ -0,0 +1 @@
+../common/logo-hochschule-bochum-cvh-text-v2.pdf
\ No newline at end of file
diff --git a/20231207/logo-hochschule-bochum.pdf b/20231207/logo-hochschule-bochum.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1
--- /dev/null
+++ b/20231207/logo-hochschule-bochum.pdf
@@ -0,0 +1 @@
+../common/logo-hochschule-bochum.pdf
\ No newline at end of file
diff --git a/20231207/pgslides.sty b/20231207/pgslides.sty
new file mode 120000
index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64
--- /dev/null
+++ b/20231207/pgslides.sty
@@ -0,0 +1 @@
+../common/pgslides.sty
\ No newline at end of file
diff --git a/20231207/trigger-01.txt b/20231207/trigger-01.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b47a7d934bde6e03b8e44141d4e7d4f233ec4b71
--- /dev/null
+++ b/20231207/trigger-01.txt
@@ -0,0 +1,62 @@
+testdb=> create table account_log ( account_id integer, change integer, timestamp timestamp );
+CREATE TABLE
+testdb=> alter table account_log drop column timestamp;
+ALTER TABLE
+testdb=> alter table account_log create column datetime timestamp;
+FEHLER:  Syntaxfehler bei »create«
+ZEILE 1: alter table account_log create column datetime timestamp;
+                                 ^
+testdb=> alter table account_log add column datetime timestamp;
+ALTER TABLE
+testdb=> \d account_log
+                             Tabelle »public.account_log«
+   Spalte   |             Typ             | Sortierfolge | NULL erlaubt? | Vorgabewert
+------------+-----------------------------+--------------+---------------+-------------
+ account_id | integer                     |              |               |
+ change     | integer                     |              |               |
+ datetime   | timestamp without time zone |              |               |
+
+testdb=> create trigger after_update_account after update on account for each row begin if new.balance <> old.balance then insert into account_log ( account_id, change, datetime ) values ( new.id, new.balance - old.balance, now () ) end;
+FEHLER:  Syntaxfehler bei »begin«
+ZEILE 1: ...date_account after update on account for each row begin if n...
+                                                              ^
+testdb=> create procedure log_change (account_id integer, change integer) language sql as 'INSERT INTO account_log (account_id, change, datetime) values (account_id, change, now ())';   CREATE PROCEDURE
+testdb=> create trigger after_update_account after update on account for each row log_change (old.account_id, new.balance - old. balance);                                                FEHLER:  Syntaxfehler bei »log_change«
+ZEILE 1: ...date_account after update on account for each row log_change...
+                                                              ^
+testdb=> create trigger after_update_account after update on account for each row call log_change (old.account_id, new.balance - old. balance);
+FEHLER:  Syntaxfehler bei »call«
+ZEILE 1: ...date_account after update on account for each row call log_c...
+                                                              ^
+testdb=> drop procedure log_change;
+DROP PROCEDURE
+testdb=> create function log_change (account_id integer, change integer) returns trigger language sql as 'INSERT INTO account_log (account_id, change, datetime) values (account_id, change, now ())';
+FEHLER:  SQL-Funktionen können keinen Rückgabetyp »trigger« haben
+testdb=> create function log_change (account_id integer, change integer) returns trigger language plpgsql as 'BEGIN; INSERT INTO account_log (account_id, change, datetime) values (account_id, change, now ()); END;';
+FEHLER:  Triggerfunktionen können keine deklarierten Argumente haben
+TIP:  Auf die Argumente des Triggers kann stattdessen über TG_NARGS und TG_ARGV zugegriffen werden.
+KONTEXT:  Kompilierung der PL/pgSQL-Funktion »log_change« nahe Zeile 1
+testdb=> create function log_change () returns trigger language plpgsql as 'BEGIN; INSERT INTO account_log (account_id, change, datetime) values (account_id, change, now ()); END;';     FEHLER:  Syntaxfehler bei »;«
+ZEILE 1: ...ange () returns trigger language plpgsql as 'BEGIN; INSERT I...
+                                                              ^
+testdb=> create function log_change () returns trigger language plpgsql as $$                testdb$> if new.balance <> old.balance then
+testdb$>   insert into log
+
+testdb$>   insert into log_change (account_id, change, datetime) values (old.id, new.balance - old.balance, now ());
+testdb$> end if;
+testdb$> return new;
+testdb$> end;
+testdb$> $$
+testdb-> ;
+FEHLER:  Syntaxfehler bei »if«
+ZEILE 2: if new.balance <> old.balance then
+         ^
+testdb=> create function log_change () returns trigger language plpgsql as $$                begin if new.balance <> old.balance then                                                       insert into log_change (account_id, change, datetime) values (old.id, new.balance - old.balance, now ());
+end if;
+return new;
+end;
+$$
+;
+CREATE FUNCTION
+testdb=> create trigger after_update_account after update on account for each row execute procedure log_change ();
+CREATE TRIGGER                                                                               testdb=>
diff --git a/20231207/trigger-02.txt b/20231207/trigger-02.txt
new file mode 100644
index 0000000000000000000000000000000000000000..11c7709bbdd358a504c4c0f6c7e92ff48ff20d46
--- /dev/null
+++ b/20231207/trigger-02.txt
@@ -0,0 +1,26 @@
+testdb=> \d                                                                                                 Liste der Relationen
+ Schema |       Name       |   Typ   | Eigentümer
+--------+------------------+---------+------------
+ public | account          | Tabelle | dbs
+ public | account_id_seq   | Sequenz | dbs
+ public | account_log      | Tabelle | dbs
+ public | cd               | Tabelle | dbs
+ public | cd_cd_id_seq     | Sequenz | dbs
+ public | customer         | Tabelle | dbs
+ public | customer_id_seq  | Sequenz | dbs
+ public | interpret        | Tabelle | dbs
+ public | interpret_id_seq | Sequenz | dbs
+ public | lied             | Tabelle | dbs
+ public | lied_auf_cd      | Sicht   | dbs
+ public | test             | Tabelle | dbs
+ public | tier             | Tabelle | dbs
+ public | tier_id_seq      | Sequenz | dbs
+(14 Zeilen)
+
+testdb=> call transfer (2, 1, 10);                                                           FEHLER:  Relation »log_change« existiert nicht
+ZEILE 1: insert into log_change (account_id, change, datetime) values...
+                     ^
+ANFRAGE:  insert into log_change (account_id, change, datetime) values (old.id, new.balance - old.balance, now ())
+KONTEXT:  PL/pgSQL-Funktion log_change() Zeile 3 bei SQL-Anweisung
+SQL-Funktion »transfer« Anweisung 1
+testdb=>
diff --git a/20231207/trigger-03.txt b/20231207/trigger-03.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0c307ff7b17641af9382752311c91fae17a01f11
--- /dev/null
+++ b/20231207/trigger-03.txt
@@ -0,0 +1,21 @@
+testdb=> create function log_change () returns trigger language plpgsql as $$                begin if new.balance <> old.balance then                                                       insert into account_log (account_id, change, datetime) values (old.id, new.balance - old.balance, now ());
+end if;
+return new;
+end;
+$$
+;
+FEHLER:  Funktion »log_change« existiert bereits mit den selben Argumenttypen
+testdb=> drop function log_change;
+FEHLER:  kann Funktion log_change() nicht löschen, weil andere Objekte davon abhängen
+DETAIL:  Trigger after_update_account für Tabelle account hängt von Funktion log_change() ab
+TIP:  Verwenden Sie DROP ... CASCADE, um die abhängigen Objekte ebenfalls zu löschen.
+testdb=> create or replace function log_change () returns trigger language plpgsql as $$
+begin if new.balance <> old.balance then
+  insert into account_log (account_id, change, datetime) values (old.id, new.balance - old.balance, now ());
+end if;
+return new;
+end;
+$$
+;
+CREATE FUNCTION
+testdb=>
diff --git a/20231207/trigger-04.txt b/20231207/trigger-04.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3f043fd90266375f886a79acdd5fcd8e114c7ad9
--- /dev/null
+++ b/20231207/trigger-04.txt
@@ -0,0 +1,22 @@
+testdb=> call transfer (2, 1, 10);                                                           CALL
+testdb=> select * from customer;
+ id |  lastname  | firstname | account_id                                                    ----+------------+-----------+------------
+  2 | Mustermann | Erika     |          1
+  4 | Rich       | Richie    |          2
+(2 Zeilen)
+
+testdb=> select * from account;
+ id |           number            | balance
+----+-----------------------------+---------
+  1 | DE12 3456 7890 ABCD EFGH IJ | 1000009
+  2 | DE98 7654 3210 ABCD EFGH IJ | 3999990
+(2 Zeilen)
+
+testdb=> select * from account_log;
+ account_id | change |          datetime
+------------+--------+----------------------------
+          1 |     10 | 2023-12-07 12:07:38.614305
+          2 |    -10 | 2023-12-07 12:07:38.614305
+(2 Zeilen)
+
+testdb=>