# Aufgabe 1
## 1. Tabelle Benutzer anlegen
``` sql
CREATE TABLE benutzer (  
	id                BIGINT       AUTO_INCREMENT PRIMARY KEY,  
	name              VARCHAR(200) NOT NULL,  
	email             VARCHAR(100) NOT NULL UNIQUE,  
	passwort          VARCHAR(200) NOT NULL,  
	admin             TINYINT(1)   NOT NULL DEFAULT 0,  
	anzahlfehler      INT          NOT NULL DEFAULT 0,  
	anzahlanmeldungen INT          NOT NULL DEFAULT 0,  
	letzteanmeldung   DATETIME              DEFAULT NULL,  
	letzterfehler     DATETIME              DEFAULT NULL  
);
```
## 3. Admin anlegen
```sql
INSERT INTO benutzer (name, email, passwort, admin)  
VALUES ('admin', 'admin@emensa.example',  '2e2b6533a81bc15430cf65de46dc097eeb5ba70c', 1);
-- '2e2b6533a81bc15430cf65de46dc097eeb5ba70c' = 'passwort'
```
## 9. Transaktion
`mysqli_begin_transaction` und `mysqli_commit` sind Funktionen, die im Zusammenhang mit Transaktionen in MySQL verwendet werden. Eine Transaktion ist eine Sequenz von Datenbankoperationen, die als eine einzige logische Einheit ausgeführt wird. Transaktionen gewährleisten, dass entweder alle Operationen erfolgreich durchgeführt werden oder keine von ihnen, wenn ein Fehler auftritt. Dieses Konzept wird als ACID-Eigenschaften bekannt: Atomarität, Konsistenz, Isolation und Dauerhaftigkeit.
- **`mysqli_begin_transaction`:** Diese Funktion startet eine neue Transaktion. Ab diesem Punkt können mehrere SQL-Operationen ausgeführt werden, die entweder alle gleichzeitig bestätigt (commited) oder abgebrochen (rolled back) werden. Das heißt, keine der Operationen ist für andere Verbindungen sichtbar, bis sie bestätigt werden.
- **`mysqli_commit`:** Diese Funktion wird verwendet, um alle Änderungen, die während der Transaktion gemacht wurden, zu bestätigen und dauerhaft in der Datenbank zu speichern. Nach dem Aufruf dieser Funktion werden alle Änderungen für andere Benutzer und Prozesse sichtbar.

Im Kontext des gegebenen PHP-Codes wird eine Transaktion verwendet, um die Sicherheit und Integrität der Datenbank zu erhöhen, wenn die Informationen eines Benutzers aktualisiert werden. Hier ist ein Überblick über die Abläufe in der Funktion `anmelden`:
1. Eine Verbindung zur Datenbank wird hergestellt (`connectdb`).
2. Es wird ein SQL-Select-Statement ausgeführt, um den Benutzer mit der spezifizierten E-Mail zu finden.
3. Wenn kein Passwort für den Benutzer gesetzt ist, wird die Funktion frühzeitig mit einem Rückgabewert von 0 beendet.
4. Wenn das Passwort des Benutzers übereinstimmt, werden die folgenden Schritte innerhalb einer Transaktion durchgeführt:
    - Die Transaktion wird mit `mysqli_begin_transaction` begonnen.
    - Ein Update-Statement wird vorbereitet und ausgeführt, um die `letzteanmeldung` auf die aktuelle Zeit und `anzahlfehler` auf 0 zu setzen.
    - Ein weiteres Update-Statement wird vorbereitet und ausgeführt, um die `anzahlanmeldungen` um eins zu erhöhen.
    - Die Transaktion wird mit `mysqli_commit` abgeschlossen.
    - Sitzungsvariablen werden gesetzt, und die Funktion gibt 1 zurück, was eine erfolgreiche Anmeldung bedeutet.
5. Wenn das Passwort nicht übereinstimmt, wird ebenfalls eine Transaktion durchgeführt:
    - Die Transaktion wird mit `mysqli_begin_transaction` begonnen.
    - Ein Update-Statement wird vorbereitet und ausgeführt, um `anzahlfehler` um eins zu erhöhen und `letzterfehler` auf die aktuelle Zeit zu setzen.
    - Die Transaktion wird mit `mysqli_commit` abgeschlossen.
    - Die Funktion gibt 0 zurück, was eine fehlgeschlagene Anmeldung bedeutet.

Durch die Verwendung von Transaktionen wird sichergestellt, dass, wenn z.B. ein Fehler bei einer der Update-Operationen auftritt oder die Verbindung zur Datenbank verloren geht, keine teilweise aktualisierten Daten zurückbleiben, was zu Inkonsistenzen führen könnte. Stattdessen würde die gesamte Transaktion automatisch zurückgerollt oder abgebrochen werden (`rollback`), sodass die Datenbank in einem konsistenten Zustand bleibt.

# Aufgabe 2
```sql
ALTER TABLE gericht ADD bildname varchar(200);

UPDATE gericht SET bildname = '01_bratkartoffel.jpg' WHERE id=1;
UPDATE gericht SET bildname = '03_bratkartoffel.jpg' WHERE id=3;
UPDATE gericht SET bildname = '04_tofu.jpg' WHERE id=4;
UPDATE gericht SET bildname = '09_suppe.jpg' WHERE id=9;
UPDATE gericht SET bildname = '06_lasagne.jpg' WHERE id=6;
UPDATE gericht SET bildname = '10_forelle.jpg' WHERE id=10;
UPDATE gericht SET bildname = '11_soup.jpg' WHERE id=11;
UPDATE gericht SET bildname = '12_kassler.jpg' WHERE id=12;
UPDATE gericht SET bildname = '13_reibekuchen.jpg' WHERE id=13;
UPDATE gericht SET bildname = '15_pilze.jpg' WHERE id=15;
UPDATE gericht SET bildname = '17_broetchen.jpg' WHERE id=17;
UPDATE gericht SET bildname = '19_mousse.jpg' WHERE id=19;
UPDATE gericht SET bildname = '20_suppe.jpg' WHERE id=20;
```

# Aufgabe 3
1. Composer installieren
    1. **Download der Composer-Installer-EXE:** Gehen Sie zur offiziellen Composer-Website [getcomposer.org](https://getcomposer.org/) und klicken Sie auf den Button "Download" oder direkt auf "Composer-Setup.exe", um den Installer für Windows herunterzuladen.
    2. **Ausführen des Installers:** Führen Sie die heruntergeladene "Composer-Setup.exe"-Datei aus. Es wird ein Installationsassistent gestartet.
    3. **Installationsoptionen:** Folgen Sie den Anweisungen im Installationsassistenten. Der Assistent wird Sie nach dem Pfad zur PHP-Executable fragen. Wenn Sie PHP bereits installiert haben und die Umgebungsvariable `PATH` gesetzt ist, kann der Assistent PHP automatisch finden. Falls nicht, müssen Sie den Pfad zur PHP-Executable (`php.exe`) manuell angeben.
    4. **Abschluss der Installation:** Führen Sie den Installationsprozess durch. Am Ende können Sie die Option aktivieren, um die Befehlszeileneingabe zu ändern und den Pfad zu Composer in die Windows-Umgebungsvariable `PATH` aufzunehmen. Damit wird Composer global zugänglich gemacht.
    5. **Überprüfung der Installation:** Öffnen Sie nach Abschluss der Installation die Kommandozeile (CMD) oder PowerShell und geben Sie `composer` ein, um zu überprüfen, ob Composer erfolgreich installiert wurde. Wenn alles korrekt installiert wurde, sollten Informationen und verfügbare Befehle von Composer angezeigt werden.
2. Abhängigkeiten laden
    1. Verzeichnis `./emensa` wechseln
    2.  `composer require monolog/monolog`  ausführen

# Aufgabe 4

```sql
-- a)
CREATE OR REPLACE 
    VIEW view_suppengerichte
    AS select * from gericht 
             WHERE name LIKE '%suppe%';

-- b)
CREATE OR REPLACE 
    VIEW view_anmeldungen 
    AS select name,anzahlanmeldungen 
    from benutzer 
        ORDER BY anzahlanmeldungen DESC;

-- c)
CREATE OR REPLACE VIEW view_kategoriegerichte_vegetarisch 
    AS select gericht.name as gericht_name, 
              vegetarisch, 
              kategorie.name as katergorie_name
                  from gericht, kategorie
                  WHERE vegetarisch = 1 ;
```

# Aufgabe 5
## Was ist eine SQL-Prozedur
Eine SQL-Prozedur ist eine Sammlung von SQL-Anweisungen, die unter einem Namen gespeichert werden und bei Bedarf aufgerufen werden können. Die Struktur einer SQL-Prozedur umfasst in der Regel zusammengesetzte Anweisungen, die durch die Schlüsselwörter BEGIN und END begrenzt sind[1]. Gespeicherte Prozeduren ermöglichen es, komplexe Abläufe von Anweisungen vom Datenbank-Client auszuführen und sind somit ein eigenständiger Befehl, der eine Abfolge gespeicherter Befehle darstellt[2].

Diese Prozedur kann dann mithilfe des Befehls EXECUTE aufgerufen werden.

Gespeicherte Prozeduren bieten Vorteile wie die Wiederverwendbarkeit von Code, die Verbesserung der Leistung und die Reduzierung von Netzwerkverkehr, da die gespeicherten Prozeduren einmal erstellt und dann mehrmals aufgerufen werden können[2].

Quellen:
1. https://www.ibm.com/docs/de/db2/11.1?topic=procedures-structure-sql
2. https://de.wikipedia.org/wiki/Gespeicherte_Prozedur
3. https://www.ibm.com/docs/de/SSEPGG_11.1.0/com.ibm.db2.luw.sql.ref.doc/doc/r0008329.html
4. https://learn.microsoft.com/de-de/sql/relational-databases/stored-procedures/create-a-stored-procedure?view=sql-server-ver16
5. https://learn.microsoft.com/de-de/sql/relational-databases/stored-procedures/execute-a-stored-procedure?view=sql-server-ver16

## Lösung
### a) 
``` sql
CREATE PROCEDURE incrementAnzahlAnmeldungen (IN benutzerid INT)
BEGIN
   UPDATE benutzer
      SET anzahlanmeldungen = anzahlanmeldungen + 1
   WHERE id = benutzerid;
END;
```
Die Prozedur die in M5_5.sql hinterlegt ist, muss einmal manuell ausgeführt werden.

### c)
Die Anwendung die am naheliegensten sind, wären das Incrementieren der `anzahlfehler` analog zu Teilaufgabe (a).
Darüber hinaus könnten alle Queries als Stored Procedures von der
Emensa-Werbeseite aufgerufen werden und dies hätte mehrere Vorteile.
Zum einen hätte es einen _Security-Vorteil_, wenn alle Queries der Werbeseiten als
Proceduren gespeichert werden würedn. Dadruch wäre es nähmlich möglich alle
erwarteten Queries abzuspeichern und der Werbeseite nur die _Berechtigung zum
Verwenden von Stored-Procedures_ zu geben. Dadurch kann nur noch in definierten
Schnittstellen mit der Dankenbank interagiert werden.
Darüber hinaus hat es wohl auch einen Vorteil gegenüber SQL-Injections.
Ein letzter Vorteil wäre, dass im PHP-Code einfach kurz die Prozedur aufgerufen
werdne kann statt lange Query-Strings zu haben.
Somit würde ich wahrscheinlich - alleine für die _Lesbarkeit_  - diese Query in
eine Stored Procedure auslagern.
Ein weiterer Vorteil wäre, dass Stored-Procedures _vor-opitimiert_ sind.
Darüber hinaus kann durch das Speichern der Queries in der Datenbank
Businesslogik "bewahren" unabhängig von git.
... Verkapselung....
