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

Vorbereitung 4.12.2024

parent 78a47ee2
No related branches found
No related tags found
No related merge requests found
../common/Zeichen_123.pdf
\ No newline at end of file
File added
% dbs-20241204.pdf - Lecture Slides on Databases and Information Security
% Copyright (C) 2023, 2024 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: Relationale Datenbanken: Normalformen, Verknüpfungen, Sichten, …
\documentclass[10pt,t]{beamer}
\usepackage{pgslides}
\usepackage{tikz}
\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{4.\ Dezember 2024}
\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}
\begin{itemize}
\vspace*{-\smallskipamount}
\item[\textbf{\dots}]
\color{medgreen}
\item[3.10] Firewall
\end{itemize}
\item[\textbf{4}] \textbf{Relationale Datenbanken}
\begin{itemize}
\color{orange}
\item[4.1] Einführung in DBMS
\item[4.2] Einführung in SQL
\color{red}
\item[4.3] Normalformen
\item[4.4] Verknüpfungen von Tabellen
\item[4.5] Sichten
\item[4.6] Schlüsselfelder
\item[4.7] Datensicherung
\end{itemize}
\vspace*{-\smallskipamount}
\item[\textbf{\dots}]
\end{itemize}
\vfilll
\underconstruction
\end{frame}
\setcounter{section}{2}
\section{Kurzeinführung TCP/IP}
\setcounter{subsection}{9}
\subsection{Firewall}
\begin{frame}
\showsubsection
\begin{itemize}
\item
\begin{picture}(0,0)
\color{red}
\put(0,0.3){\makebox(0,0)[tl]{{\tikz{\draw[line width=1pt](0,0)--(6,-0.8);}}}}
\put(0,0.3){\makebox(0,0)[tl]{{\tikz{\draw[line width=1pt](0,-0.8)--(6,0);}}}}
\end{picture}%
magische Hardware und/oder Software,\\
die uns vor allen Angriffen schützt
\item
Paketfilter (Internet- und Transportschicht: IP-Adressen, Port-Nummern)
% \pause
\begin{itemize}
\item
Stateful Packet Inspection (Transportschicht)
\item
Deep Packet Inspection (Anwendungsschicht)
\end{itemize}
\item
Proxy (Anwendungsschicht)
\begin{itemize}
\item
Anfragen verstehen,\\
stellvertretend für die Anwendung beim Server anfragen
\arrowitem
mehrere Anfragen bündeln: weniger Netzlast
\arrowitem
Inhalte filtern: Malware erkennen,\\
aber auch "`politisch unerwünschte"' Inhalte
\end{itemize}
\end{itemize}
\vfilll
\begin{center}
\renewcommand{\arraystretch}{1.2}
\begin{tabular}{|l|}\hline
Anwendung: HTTP, SMTP, \dots \\\hline
Transport: TCP-/UDP-Ports, ICMP \\\hline
Internet: IP-Adresse \\\hline
Netzwerkzugang: Hardware-/MAC-Adresse \\\hline
\end{tabular}
\end{center}
\end{frame}
\section{Relationale Datenbanken}
\subsection{Einführung in DBMS}
\begin{frame}[fragile]
\showsection
\showsubsection
Datenbank-Management-System (DBMS): z.\,B.\ PostgreSQL, MariaDB
\begin{itemize}
\item Datenbanken "`von außen"' verwalten (z.\,B.\ auflisten)
\item Schnittstelle für Zugriff auf Datenbank
\item \textbf{in hohem Maße herstellerspezifisch}
\end{itemize}
\bigskip
\begin{onlyenv}<1>
\footnotesize
\begin{lstlisting}[style=terminal,gobble=6]
root@cassini:~# ¡su - postgres¿
postgres@cassini:~$ ¡psql¿
psql (15.3 (Debian 15.3-0+deb12u1))
Geben Sie »help« für Hilfe ein.
postgres=# ¡help¿
Dies ist psql, die Kommandozeilenschnittstelle für PostgreSQL.
Geben Sie ein: \copyright für Urheberrechtsinformationen
\h für Hilfe über SQL-Anweisungen
\? für Hilfe über interne Anweisungen
\g oder Semikolon, um eine Anfrage auszuführen
\q um zu beenden
postgres=#
\end{lstlisting}
\vspace*{-3cm}
\end{onlyenv}
\begin{onlyenv}<2>
\footnotesize
\begin{lstlisting}[style=terminal,gobble=6]
postgres=# ¡\?¿
Allgemein
\copyright PostgreSQL-Urheberrechtsinformationen zeigen
\crosstabview [SPALTEN] Anfrage ausführen und Ergebnis als Kreuztabelle
anzeigen
\errverbose letzte Fehlermeldung mit vollen Details anzeigen
\g [(OPT)] [DATEI] SQL-Anweisung ausführen (und Ergebnis in Datei
oder |Pipe schreiben); ...
... ...
\q psql beenden
... ...
postgres=#
\end{lstlisting}
\vspace*{-3cm}
\end{onlyenv}
\begin{onlyenv}<3>
\footnotesize
\begin{lstlisting}[style=terminal,gobble=6]
postgres=# ¡\l¿
Liste der Datenbanken
Name | Eigentümer | Kodierung | Sortierfolge | Zeichentyp |
-----------+------------+-----------+--------------+-------------+- ···
postgres | postgres | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 |
template0 | postgres | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 |
| | | | |
template1 | postgres | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 |
| | | | | ...
(3 Zeilen)
postgres=#
\end{lstlisting}
\vspace*{-3cm}
\end{onlyenv}
\end{frame}
\subsection{Einführung in SQL}
\begin{frame}[fragile]
\showsection
\showsubsection
Datenbank-Abfragesprache: Structured Query Language (SQL)
\begin{itemize}
\item Datenbanken "`von innen"' verwalten, z.\,B.\ anlegen und wieder löschen
\item Daten in der Datenbank bearbeiten
\item \textbf{in hohem Maße standardisiert}
\end{itemize}
\bigskip
\begin{onlyenv}<1>
\footnotesize
\begin{lstlisting}[style=terminal,gobble=6]
postgres=# ¡create database testdb;¿
CREATE DATABASE
postgres=# ¡create user dbsadmin with password '####';¿
CREATE ROLE
postgres=# ¡create user dbs with password '####';¿
CREATE ROLE
postgres=# ¡ALTER DATABASE testdb OWNER TO dbsadmin;¿
ALTER DATABASE
postgres=# ¡\q¿
postgres@cassini:~$
\end{lstlisting}
\vspace*{-3cm}
\end{onlyenv}
\begin{onlyenv}<2>
\footnotesize
\begin{lstlisting}[style=terminal,gobble=6]
$ ¡psql -h localhost -U dbsadmin -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=> ¡grant select, insert, update on tier to dbs;¿
GRANT
testdb=> ¡\q¿
\end{lstlisting}
\vspace*{-3cm}
\end{onlyenv}
\begin{onlyenv}<3>
\footnotesize
\begin{lstlisting}[style=terminal,gobble=6]
$ ¡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=> ¡drop table tier;¿
FEHLER: Berechtigung nur für Eigentümer der Tabelle tier
testdb=>
\end{lstlisting}
\vspace*{-3cm}
\end{onlyenv}
\end{frame}
\begin{frame}
\showsection
\showsubsection
Datenbank-Abfragesprache: Structured Query Language (SQL)
\bigskip
Literatur: z.\,B.\ \url{https://de.wikibooks.org/wiki/Einführung_in_SQL}
\bigskip
Wichtige SQL-Befehle:
\begin{itemize}
\item
\lstinline[style=cmd]{CREATE} -- Datenbanken, Tabellen usw.\ anlegen
\item
\lstinline[style=cmd]{DROP} -- Datenbanken, Tabellen usw.\ löschen
\item
\lstinline[style=cmd]{SELECT} -- Daten abfragen
\item
\lstinline[style=cmd]{INSERT INTO ... VALUES} -- Daten eingeben
\item
\lstinline[style=cmd]{UPDATE} -- Daten ändern
\item
\lstinline[style=cmd]{DELETE FROM} -- Daten löschen
\end{itemize}
\end{frame}
\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<2->{\color{red}\textarrow\ 1.~Normalform}}
\item
Speichern von denselben Daten in verschiedenen Tabelleneinträgen\\
{\only<2->{\color{red}\textarrow\ 2.~Normalform}}
\item
implizite Zusammenhänge\\
{\only<2->{\color{red}\textarrow\ 3.~Normalform und Boyce-Codd-Normalform}}
\item
voneinander unabhängige Zusammenhänge in derselben Tabelle\\
{\only<2->{\color{red}\textarrow\ 4.~und 5.~Normalform}}
\end{itemize}
\begin{onlyenv}<2->
\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}
\iffalse
\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}[fragile]
\showsection
\showsubsection
Problem:
\begin{itemize}
\item
Ein böswilliger Benutzer gibt über eine Benutzerschnittstelle
(z.\,B.\ ein Web-Interface) Daten ein (z.\,B.\ einen "`Namen"'),
die Sonderzeichen enthalten, damit sie als SQL-Befehle ausgeführt werden.
\item
Literatur: \url{https://xkcd.com/327/}
\end{itemize}
\medskip
Lösung: Die Benutzerschnittstelle prüft die Daten auf Sonderzeichen\\
und ersetzt diese durch geeignete Escape-Sequenzen
\begin{itemize}
\item
\lstinline[style=cmd]{'} durch \lstinline[style=cmd]{''} ersetzen
\item
Funktion \lstinline[style=cmd]{CHR()}
\item
Viele DBMS verstehen ein vorangestelltes \lstinline[style=cmd]{\}.
\end{itemize}
\medskip
Bessere Lösung: \newterm{Prepared Statements}
\begin{itemize}
\item
\url{https://www.postgresql.org/docs/current/sql-prepare.html}
\item
\url{https://www.w3schools.com/php/php_mysql_prepared_statements.asp}
\end{itemize}
\end{frame}
\subsection{Datensicherheit bei Datenbanken}
\begin{frame}
\showsection
\showsubsection
\begin{itemize}
\item
kein direkter Zugriff von außen auf die Datenbank
\item
feingranulare Benutzerrechte
\item
Software aktuell halten
\item
Prepared Statements
\item
Transportverschlüsselung
\end{itemize}
\end{frame}
\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}
\fi
\end{document}
File added
% dbs-uebung-20241204.pdf - Exercises on Databases and Information Security
% Copyright (C) 2024 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: 8: Normalformen
\documentclass[a4paper]{article}
\usepackage{pgscript}
\begin{document}
\thispagestyle{empty}
\section*{Datenbanken und Datensicherheit\\
Übungsaufgaben 8 -- 4.\ Dezember 2024}
\exercise{Normalformen}
Welche Normalformen verletzen die untenstehenden Tabellen?\\
Auf welche Weise ließe sich das beheben?
\begin{enumerate}[(a)]
\item
\begin{tabular}[t]{l|l|l|l|l}
Name & Matr.-Nr.\ & Hobby 1 & Hobby 2 & Hobby 3 \\\hline
Antonia & 12345 & Gitarre & Fechten & --- \rule{0pt}{2ex}\\
Bert & 23456 & Fußball & --- & --- \\
Casimir & 34567 & Stepptanz & Malen & Reiten \\
Dora & 45678 & Fußball & Reiten & Schlagzeug
\end{tabular}
\item
\begin{tabular}[t]{l|l|l}
Name & Matr.-Nr.\ & Hobby \\\hline
Antonia & 12345 & Gitarre \rule{0pt}{2ex}\\
Antonia & 12345 & Fechten \\
Bert & 23456 & Fußball \\
Casimir & 34567 & Stepptanz \\
Casimir & 34567 & Malen \\
Casimir & 34567 & Reiten \\
Dora & 45678 & Fußball \\
Dora & 45678 & Reiten \\
Dora & 45678 & Schlagzeug
\end{tabular}
\item
\begin{tabular}[t]{l|l|l}
Name & Studiengang & Hobby \\\hline
Antonia & Mathematik & Gitarre \rule{0pt}{2ex}\\
Antonia & Mathematik & Fechten \\
Bert & Pädagogik & Fußball \\
Bert & Sport & Fußball \\
Casimir & Pädagogik & Stepptanz \\
Casimir & Pädagogik & Malen \\
Casimir & Pädagogik & Reiten \\
Dora & Mathematik & Fußball \\
Dora & Chemie & Reiten \\
Dora & --- & Schlagzeug
\end{tabular}
\end{enumerate}
\begin{flushright}
\textit{Viel Erfolg!}
\end{flushright}
\end{document}
../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/pgscript.sty
\ No newline at end of file
../common/pgslides.sty
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment