Skip to content
Snippets Groups Projects
Commit 7e4a1d71 authored by Peter Gerwinski's avatar Peter Gerwinski
Browse files

Vortragsfolien und Screenshots 30.11.2023

parent 5ff51487
No related branches found
No related tags found
No related merge requests found
Showing with 749 additions and 0 deletions
../common/Zeichen_123.pdf
\ No newline at end of file
File added
% dbs-20221130.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: Transaktionen, Indizierung, GUI-Zugriff
\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{30.\ November 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.3] Normalformen
\color{medgreen}
\item[4.4] Verknüpfungen von Tabellen
\item[4.5] Sichten
\item[4.6] Schlüsselfelder
\item[4.7] Datensicherung
\color{red}
\item[4.8] Transaktionen
\item[4.9] Indizierung
\color{black}
\item[4.10] Trigger
\color{red}
\item[4.11] GUI-Zugriff
\color{black}
\item[4.12] 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}{2}
\subsection{Normalformen}
\begin{frame}
\showsection
\showsubsection
Problem: Schlecht angelegte Datenbanken werden schnell inkonsistent.\\
Beliebte Fehler:
\begin{itemize}
\item
Speichern von mehreren Daten in demselben Tabelleneintrag\\
{\only<1->{\color{red}\textarrow\ 1.~Normalform}}
\item
Speichern von denselben Daten in verschiedenen Tabelleneinträgen\\
{\only<1->{\color{red}\textarrow\ 2.~Normalform}}
\item
implizite Zusammenhänge\\
{\only<1->{\color{red}\textarrow\ 3.~Normalform und Boyce-Codd-Normalform}}
\item
voneinander unabhängige Zusammenhänge in derselben Tabelle\\
{\only<1->{\color{red}\textarrow\ 4.~und 5.~Normalform}}
\end{itemize}
\begin{onlyenv}<1->
\medskip
{\color{red}Lösung: Normalformen}
\end{onlyenv}
\bigskip
Literatur: z.\,B.\ \url{https://de.wikipedia.org/wiki/Normalisierung_(Datenbank)}
\end{frame}
\subsection{Verknüpfungen von Tabellen}
\begin{frame}
\showsection
\showsubsection
Problem: Gut angelegte Datenbanken ({\color{red}\textarrow\ Normalformen})\\
sind stark aufgesplittet.\\
Wie kann man sie weiterhin effizient benutzen?
\bigskip
Lösung: Verknüpfungen von Tabellen
\bigskip
SQL-Befehl: \lstinline[style=cmd]{JOIN}
\bigskip
Literatur: z.\,B.\ \url{https://de.wikipedia.org/wiki/SQL}
\end{frame}
\begin{frame}[fragile]
\showsection
\showsubsection
Was machen wir mit Tabelleneinträgen,\\
bei denen die \lstinline[style=cmd]{ON}-Bedingung
nicht erfüllt ist?
\medskip
\begin{lstlisting}[style=terminal]
¡SELECT <Feld[er]> FROM <Tabelle1> [INNER] JOIN <Tabelle2>
ON <Tabelle1>.<Feld> = <Tabelle2>.<Feld>;¿
\end{lstlisting}
\smallskip
\begin{itemize}
\arrowitem
weglassen: \lstinline[style=cmd]{[INNER] JOIN}
\end{itemize}
\medskip
\begin{lstlisting}[style=terminal]
¡SELECT <Feld[er]> FROM <Tabelle1> LEFT JOIN <Tabelle2>
ON <Tabelle1>.<Feld> = <Tabelle2>.<Feld>;¿
\end{lstlisting}
\smallskip
\begin{itemize}
\arrowitem
linke Tabelle trotzdem anzeigen
(mit \lstinline[style=cmd]{NULL}-Einträgen):
\lstinline[style=cmd]{LEFT JOIN}\\
(analog: \lstinline[style=cmd]{RIGHT JOIN} für rechte Tabelle)
\end{itemize}
\medskip
\begin{lstlisting}[style=terminal]
¡SELECT <Feld[er]> FROM <Tabelle1> FULL JOIN <Tabelle2>
ON <Tabelle1>.<Feld> = <Tabelle2>.<Feld>;¿
\end{lstlisting}
\smallskip
\begin{itemize}
\arrowitem
beide Tabellen trotzdem anzeigen
(mit \lstinline[style=cmd]{NULL}-Einträgen):
\lstinline[style=cmd]|FULL JOIN|
\end{itemize}
\end{frame}
\subsection{Sichten}
\begin{frame}[fragile]
\showsection
\showsubsection
\begin{lstlisting}[style=terminal]
¡SELECT <Feld[er]> FROM <Tabelle1> [INNER] JOIN <Tabelle2>
ON <Tabelle1>.<Feld> = <Tabelle2>.<Feld>;¿
\end{lstlisting}
\smallskip
\begin{itemize}
\arrowitem
Wir betrachten beide Tabellen zusammen als eine große Tabelle.
\end{itemize}
\medskip
\begin{lstlisting}[style=terminal]
¡CREATE VIEW <Sicht> AS
SELECT <Feld[er]> FROM <Tabelle1> JOIN <Tabelle2>
ON <Tabelle1>.<Feld> = <Tabelle2>.<Feld>;
SELECT <Feld[er]> FROM <Sicht> [WHERE ...];¿
\end{lstlisting}
\smallskip
\begin{itemize}
\arrowitem
Wir sprechen das Ergebnis genau wie eine Tabelle an.
\bigskip
\arrowitem
Es ist möglich, ohne Verlust an Komfort alle Daten in Normalform zu halten.
\end{itemize}
\end{frame}
\subsection{Schlüsselfelder}
\begin{frame}[fragile]
\showsection
\showsubsection
\begin{lstlisting}[style=terminal]
¡CREATE TABLE tabelle1 (
id INT PRIMARY KEY AUTO_INCREMENT,
...
);
CREATE TABLE tabelle2 (
...
tabelle1_id INT,
...
FOREIGN KEY(tabelle1_id) REFERENCES tabelle1(id)
);
\end{lstlisting}
\smallskip
\begin{itemize}
\arrowitem
Dem DBMS mitteilen, welche Felder für \lstinline[style=cmd]{JOIN}
vorgesehen sind.
\arrowitem
Das DBMS kann mit auf Konsistenz achten.
\end{itemize}
\end{frame}
\subsection{Datensicherung}
\begin{frame}[fragile]
\showsection
\showsubsection
\begin{lstlisting}[style=terminal]
$ ¡pg_dump --clean -h <Rechner> -U <User> -W <Datenbank>¿
\end{lstlisting}
\smallskip
\begin{itemize}
\item
Ausgabe des gesamten Datenbankinhalts\\
als SQL-Quelltext zur Standardausgabe
\arrowitem
keine Probleme mit sich evtl.\ ändernden Binärformaten
\item
Es ist möglich, den Inhalt direkt in einer Pipe weiterzuverarbeiten\\
(z.\,B.\ zu komprimieren).
\item
Zurückspielen: mit \lstinline[style=cmd]{psql}
\end{itemize}
\smallskip
\begin{lstlisting}[style=terminal]
$ ¡psql -h <Rechner> -U <User> -W <Datenbank> \
< <Ausgabe von pg_dump>¿
\end{lstlisting}
\smallskip
\begin{itemize}
\item
analog für \file{MariaDB}: \lstinline[style=cmd]{mariadb-dump}
\end{itemize}
\end{frame}
\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}
\addtocounter{subsection}{1}
\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}
\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}
testdb=> SELECT * FROM account where number = 'DE12 3456 7890 ABCD EFGH IJ';
id | number | balance
----+-----------------------------+---------
1 | DE12 3456 7890 ABCD EFGH IJ | 1000001
(1 Zeile)
testdb=> CREATE INDEX index_account_number ON account ( number );
CREATE INDEX
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=> SELECT * FROM account where number = 'DE12 3456 7890 ABCD EFGH IJ';
id | number | balance
----+-----------------------------+---------
1 | DE12 3456 7890 ABCD EFGH IJ | 1000001
(1 Zeile)
testdb=>
../common/logo-hochschule-bochum-cvh-text-v2.pdf
\ No newline at end of file
../common/logo-hochschule-bochum.pdf
\ No newline at end of file
../common/pgslides.sty
\ No newline at end of file
cassini/home/peter/bo/2023ws/dbs/20231130> psql -h localhost -U dbs -W testdb
Passwort:
psql (15.5 (Debian 15.5-0+deb12u1))
SSL-Verbindung (Protokoll: TLSv1.3, Verschlüsselungsmethode: TLS_AES_256_GCM_SHA384, Komprimierung: aus)
Geben Sie »help« für Hilfe ein.
testdb=> CREATE TABLE IF NOT EXISTS customer VALUES(id PRIMARY KEY AUTO_INCEMENR, lastname TEXT, firstname TEXT, account TEXT);
FEHLER: Syntaxfehler bei »VALUES«
ZEILE 1: CREATE TABLE IF NOT EXISTS customer VALUES(id PRIMARY KEY AU...
^
testdb=> CREATE TABLE IF NOT EXISTS customer VALUES(id AUTO_INCEMENR, lastname TEXT, firstname TEXT, account TEXT);
FEHLER: Syntaxfehler bei »VALUES«
ZEILE 1: CREATE TABLE IF NOT EXISTS customer VALUES(id AUTO_INCEMENR,...
^
testdb=> CREATE TABLE IF NOT EXISTS customer VALUES(id AUTO_INCREMENT, lastname TEXT, firstname TEXT, account TEXT);
FEHLER: Syntaxfehler bei »VALUES«
ZEILE 1: CREATE TABLE IF NOT EXISTS customer VALUES(id AUTO_INCREMENT...
^
testdb=> CREATE TABLE IF NOT EXISTS customer VALUES(id PRIMARY KEY AUTO_INCREMENT, lastname TEXT, firstname TEXT, account TEXT);
FEHLER: Syntaxfehler bei »VALUES«
ZEILE 1: CREATE TABLE IF NOT EXISTS customer VALUES(id PRIMARY KEY AU...
^
testdb=> CREATE TABLE IF NOT EXISTS customer (id PRIMARY KEY AUTO_INCREMENT, lastname TEXT, firstname TEXT, account TEXT);
FEHLER: Syntaxfehler bei »PRIMARY«
ZEILE 1: CREATE TABLE IF NOT EXISTS customer (id PRIMARY KEY AUTO_INC...
^
testdb=> CREATE TABLE IF NOT EXISTS customer (id INTEGER PRIMARY KEY AUTO_INCREMENT, lastname TEXT, firstname TEXT, account TEXT);
FEHLER: Syntaxfehler bei »AUTO_INCREMENT«
ZEILE 1: ...LE IF NOT EXISTS customer (id INTEGER PRIMARY KEY AUTO_INCRE...
^
testdb=> CREATE TABLE IF NOT EXISTS customer (id SERIAL PRIMARY KEY, lastname TEXT, firstname TEXT, account TEXT);
CREATE TABLE
testdb=>
testdb=> ALTER TABLE customer DELETE COLUMN account;
FEHLER: Syntaxfehler bei »DELETE«
ZEILE 1: ALTER TABLE customer DELETE COLUMN account;
^
testdb=> ALTER TABLE customer DROP COLUMN account;
ALTER TABLE
testdb=> ALTER TABLE customer ADD COLUMN account_id INTEGER;
ALTER TABLE
testdb=> \d
Liste der Relationen
Schema | Name | Typ | Eigentümer
--------+------------------+---------+------------
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
(11 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)
testdb=>
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)
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)
testdb=> ALTER TABLE customer ADD CONSTRAINT customer_fkey_account_id FOREIGN KEY accoun
testdb=> ALTER TABLE customer ADD CONSTRAINT customer_fkey_account_id FOREIGN KEY account_id REFER
testdb=> ALTER TABLE customer ADD CONSTRAINT customer_fkey_account_id FOREIGN KEY(account_id) REFERENCES account(id);
ALTER TABLE
testdb=>
testdb=> INSERT INTO customer (lastname, firstname, account_id) VALUES ('Mustermann', 'Erika', 1);
FEHLER: Einfügen oder Aktualisieren in Tabelle »customer« verletzt Fremdschlüssel-Constraint »customer_fkey_account_id«
DETAIL: Schlüssel (account_id)=(1) ist nicht in Tabelle »account« vorhanden.
testdb=> SELECT * FROM account; id | number | balance
----+--------+---------
(0 Zeilen)
testdb=> SELECT * FROM customer;
id | lastname | firstname | account_id
----+----------+-----------+------------
(0 Zeilen)
testdb=> INSERT INTO account (number, balance) VALUES ('DE12 3456 7890 ABCD EFGH IJ', 0);
INSERT 0 1
testdb=> SELECT * FROM account;
id | number | balance
----+-----------------------------+---------
1 | DE12 3456 7890 ABCD EFGH IJ | 0
(1 Zeile)
testdb=> INSERT INTO customer (lastname, firstname, account_id) VALUES ('Mustermann', 'Erika', 1);
INSERT 0 1
testdb=> SELECT * FROM customer;
id | lastname | firstname | account_id
----+------------+-----------+------------
2 | Mustermann | Erika | 1
(1 Zeile)
testdb=> SELECT * FROM account;
id | number | balance
----+-----------------------------+---------
1 | DE12 3456 7890 ABCD EFGH IJ | 0
(1 Zeile)
testdb=>
testdb=> UPDATE customer SET balance = 5000000 WHERE lastname = 'Rich';
FEHLER: Spalte »balance« von Relation »customer« existiert nicht
ZEILE 1: UPDATE customer SET balance = 5000000 WHERE lastname = 'Rich...
^
testdb=> UPDATE account SET balance = 5000000 WHERE lastname = 'Rich';
FEHLER: Spalte »lastname« existiert nicht
ZEILE 1: UPDATE account SET balance = 5000000 WHERE lastname = 'Rich'...
^
testdb=> UPDATE account SET balance = 5000000 WHERE (SELECT account_id FROM customer WHERE lastname = 'Rich');
FEHLER: Argument von WHERE muss Typ boolean haben, nicht Typ integer
ZEILE 1: UPDATE account SET balance = 5000000 WHERE (SELECT account_i...
^
testdb=> UPDATE account SET balance = 5000000 WHERE id = (SELECT account_id FROM customer WHERE lastname = 'Rich');
UPDATE 1
testdb=>
testdb=> UPDATE customer SET balance = 5000000 WHERE lastname = 'Rich';
FEHLER: Spalte »balance« von Relation »customer« existiert nicht
ZEILE 1: UPDATE customer SET balance = 5000000 WHERE lastname = 'Rich...
^
testdb=> UPDATE account SET balance = 5000000 WHERE lastname = 'Rich';
FEHLER: Spalte »lastname« existiert nicht
ZEILE 1: UPDATE account SET balance = 5000000 WHERE lastname = 'Rich'...
^
testdb=> UPDATE account SET balance = 5000000 WHERE (SELECT account_id FROM customer WHERE lastname = 'Rich');
FEHLER: Argument von WHERE muss Typ boolean haben, nicht Typ integer
ZEILE 1: UPDATE account SET balance = 5000000 WHERE (SELECT account_i...
^
testdb=> UPDATE account SET balance = 5000000 WHERE id = (SELECT account_id FROM customer WHERE lastname = 'Rich');
UPDATE 1
testdb=> UPDATE account JOIN customer ON customer.account_id = account.id SET account.balance = 5000001 WHERE customer.lastname = 'Rich';
FEHLER: Syntaxfehler bei »JOIN«
ZEILE 1: UPDATE account JOIN customer ON customer.account_id = accoun...
^
testdb=>
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 | 0
2 | DE98 7654 3210 ABCD EFGH IJ | 5000000
(2 Zeilen)
testdb=> UPDATE account SET balance = balance + 1000000 WHERE id = (SELECT account_id FROM customer WHERE lastname = 'Mustermann');
UPDATE 1
testdb=> UPDATE account SET balance = balance - 1000000 WHERE id = (SELECT account_id FROM customer WHERE lastname = 'Rich');
UPDATE 1
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 | 1000000
2 | DE98 7654 3210 ABCD EFGH IJ | 4000000
(2 Zeilen)
testdb=>
testdb=> BEGIN;
BEGIN
testdb=*> UPDATE account SET balance = balance + 1 WHERE id = (SELECT account_id FROM customer WHERE lastname = 'Mustermann');
UPDATE 1
testdb=*> UPDATE account SET balance = balance - 1 WHERE id = (SELECT account_id FROM customer WHERE lastname = 'Rich');
UPDATE 1
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=*> COMMIT;
COMMIT
testdb=>
testdb=> BEGIN; BEGIN
testdb=*> UPDATE account SET balance = balance + 10000000 WHERE id = (SELECT account_id FROM customer WHERE lastname = 'Mustermann');
UPDATE 1
testdb=*> UPDATE account SET balance = balance - 10000000 WHERE id = (SELECT account_id FROM customer WHERE lastname = 'Rich');
UPDATE 1
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 | 11000001
2 | DE98 7654 3210 ABCD EFGH IJ | -6000001
(2 Zeilen)
testdb=*> ROLLBACK;
ROLLBACK
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=>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment