# SQL Syntax der Txt-Db-Api (Einschränkungen)

##

## Allgemein

Die Txt-Db-Api unterstützt nicht den ganzen SQL-Sprachumfang, der unterstützte Umfang sollte jedoch
mit dem SQL Standard kompatibel sein.
Nachfolgend sind die Einschränkungen bzw. die Syntax für SQL Statements was die Txt-Db-Api betrifft aufgeführt.
Werte in [] sind freiwillig, "..." bedeutet das beliebig viele weitere Elemente folgen können,
| heisst das entweder der eine ODER der andere wert genommen werden kann.

Achtung: Wie auch im Standard definiert, sollten Werte für str (String) Felder immer in die
Anführungszeichen ' ' oder " " eingeschlossen werden!

## SELECT

### Syntax

    SELECT [DISTINCT]
    [funktion(][tabelle.]spalte[)] [AS alias_name] [, [funktion(][tabelle].spalte[)] [AS alias_name] , ...]
    FROM tabelle [AS tabellen_alias] [, tabelle2 [AS tabellen_alias], ... ]
    [[LEFT|RIGHT|INNER] [OUTER] JOIN [tabelle] ON tabelle2, ... ]
    [WHERE spalte=wert AND|OR spalte=spalte AND|OR ...]
    [GROUP BY spalte, ...]
    [ORDER BY spalte [ASC | DESC] ,...]
    [LIMIT [offset,]anzahl] [;]

### Unterstützt

- Siehe Syntax

- Anstelle von Spaltennnamen (spalte in der Syntax oben) können auch direkte Werte verwendet werden.
Das können entweder Zahlen oder Strings in ' ' oder " " sein, z.B. SELECT 1234, 'bla', name FROM personen;

- Folgende Funktionen: UNIX_TIMESTAMP(), MD5(spalte), NOW(), ABS(spalte), LCASE(spalte), UCASE(spalte), LOWER(spalte), UPPER(spalte), EVAL(spalte *-+/ wert|spalte.....)
- Die oben genannten Funktionen werden auch bei WHERE, GROUP BY und ORDER BY unterstützt
- Folgende gruppierenden Funktionen: MAX(spalte), MIN(spalte), COUNT(spalte), SUM(spalte), AVG(spalte)
- Anstelle einer spalte kann man für Funktionen auch direkte Werte als Parameter angeben, z.B. md5('bla')
- * anstelle von Feldnamen
- tabelle.* anstelle von Feldnamen, auch Kombinationen möglich z.B. SELECT personen.*, firma.Name, ort.* ...
- SELECT COUNT([table.]*)
- Aliase für Tabellen

- Im WHERE Teil werden folgende Vergleichsoperatoren unterstützt: =,>,<,>=,<=, !=, <>, LIKE / NOT LIKE (wildcards % und _), IN / NOT IN
- Im WHERE Teil kann entweder feld=wert, wert=wert oder auch feld=feld stehen
(um tabellen verknüpft abzufragen, wie z.B. im Beispiel unten "personen.typ_id = typen.id")
"=" steht hier nur als Beispiel, für Feld=Feld sind alle oben genannten Vergleichsoperatoren möglich
- Im WHERE Teil können beliebige viele AND und OR verwendet werden
- Im WHERE Teil können beliebig viele Klammern verwendet und verschachtelt werden
- JOIN's (INNER, LEFT [OUTER] und RIGHT [OUTER])
- DISTINCT: nur zeilen die sich eindeutig von andern unterscheiden werden zurückgegeben
- GROUP BY: ergebniss nach den angegebenen spalten gruppieren.

- LIMIT (nur bei SELECT): offset ist ein offset beginnend bei 0 (d.h. ein offset 1 startet bei der 2. Reihe),
welches angibt ab welcher Reihe man das Ergebnis auf anzahl Zeilen limitieren möchte.
Wenn man ein LIMIT angibt so ist anzahl obligatorisch, das offset kann auch weggelassen werden.
Beispiel: LIMIT 4,10 (Liefert nur die Zeilen von 5 bis und mit 14 zurück => Anzahl = 10)

- Bei DISTINCT und GROUP BY wird immer der erste wert genommen,
Beispiel: "SELECT time, ip FROM log GROUP BY time"

time | ip 10348395 | 192.168.0.1 10348395 | 192.168.0.3 | > | time | ip 10348395 | 192.168.0.1

### Nicht unterstützt

- Zusammenfügen von Feldern wie zB SELECT name & " " & vorname AS ganzer_name oder
SELECT name + vorname AS ganzer_name
- Alles was nicht irgendwie unter Syntax oder Unterstützt zu finden ist

### Beispiele

SELECT vorname, personen.nachname, typen.typ AS personen_typ FROM personen, typen
WHERE personen.typ_id = typen.id AND (personen.Nr>=10 OR personen.vorname='Hans')
ORDER BY vorname LIMIT 100

SELECT COUNT(t.name), AVG(t.alter) AS durchschnittsalter, k.name FROM teilnehmer AS t, kurs AS k
WHERE t.kurs_nr=kurs.id GROUP BY k.name;

SELECT md5('bla');

### Hinweise

ACHTUNG: Vor und nach jedem OR oder AND müssen je ein Leerschlag (" ") stehen.
Dies damit der Parser genau zwischen AND und OR's die eventuell zu Feldnamen gehören
oder AND und OR's die als Teil der Logik gemeint sind, unterscheiden kann !
Das gleiche gilt für LIKE!

Ungültig: Name='Test'OR Nr>20
Gültig: Name='Test' OR Nr>20

ACHTUNG: Benutzt LIKE nur wenn es zwingend nötig ist, da LIKE viel langsamer ist als ein
normaler String-Vergleich. Wenn man also alle Datensätze Abfragen will wo der ort genau 'Basel'
ist sollte man es so machen: SELECT * FROM tabelle WHERE ort='Basel'
und NICHT so: SELECT * FROM tabelle WHERE ort LIKE 'Basel'
und schon GAR NICHT so: SELECT * FROM tabelle WHERE ort LIKE '%Basel%'

## INSERT

### Syntax

    INSERT [INTO] tabelle [(spalte1, spalte2, spalte_n, ...)]
    VALUES  (  [funktion(]wert[)]  [, funktion[(]wert2[)], wert_n, ...]) [;]
    	oder
    INSERT [INTO] tabelle
    SET spalte= [funktion(] wert [)]  [, spalte2=[funktion(]wert2[)], spalte_n=[funktion(]wert_n[)], ...] [;]

### Unterstützt

- Siehe Syntax
- Folgende Funktionen: UNIX_TIMESTAMP(), MD5(wert), NOW(), ABS(wert), LCASE(wert), UCASE(wert), LOWER(wert), UPPER(wert)
- Als Parameter für die Funktionen werden hier logischerwesie nur Werte und keine Spalten unterstützt.

### Nicht unterstützt

- INSERT mit SELECT
- Mehrere Datensätze einfügen (in einem SQL Statement)
- Gruppierende Funktionen wie zB MAX(), MIN() etc. (was auch gar keinen Sinn machen würde!)
- Alles was nicht irgendwie unter Syntax zu finden ist

### Beispiele

INSERT INTO personen (vorname, nachname) VALUES ('hans','meier');

INSERT INTO passwords (user, password) VALUES ( 'user1', md5('mypassword') );

INSERT INTO personen SET vorname=upper('hans'), alter=abs(-55), eingetragen=NOW() ;

## DELETE

### Syntax

    DELETE FROM tabelle [WHERE <gleich wie bei SELECT>] [;]

###
Unterstützt

- Siehe Syntax
- Das löschen der ganzen Tabelle (kein WHERE angeben)
- Für den WHERE Teil gilt das gleiche wie bei SELECT (funktionen werden also auch unterstüzt!)

### Nicht unterstützt

- LIMIT
- Alles was nicht irgendwie unter Syntax zu finden ist

### Beispiele

DELETE FROM personen WHERE vorname='Hans';

DELETE FROM personen WHERE passwort=md5('mypw') AND abs(alter)=abs(-5);

## UPDATE

### Syntax

    UPDATE tabelle SET spalte=[funktion(]wert[)] [,spalte2=[funktion(]wert2[)], spalte_n=[funktion(]wert_n[)], ...]
    [WHERE <gleich wie bei SELECT>] [;]

###
Unterstützt

- Siehe Syntax
- Folgende Funktionen für die Werte: UNIX_TIMESTAMP(), MD5(spalte oder wert), NOW(), ABS(spalte oder wert),
LCASE(spalte oder wert), UCASE(spalte oder wert), LOWER(spalte oder wert), UPPER(spalte oder wert), EVAL(spalte *-+/ wert|spalte.....)
- Updaten der ganzen Tabelle (kein WHERE angeben)
- Zuweisen des Wertes einer Spalte an eine andere
- Für den WHERE Teil gilt das gleiche wie bei SELECT (funktionen werden also auch unterstüzt!)

### Nicht unterstützt

- LIMIT
- ORDER BY
- Alles was nicht irgendwie unter Syntax zu finden ist

### Beispiele

UPDATE personen SET vorname='Hans2000' WHERE vorname='Hans';
UPDATE personen SET vorname=nachname WHERE vorname='Hans';
UPDATE personen SET passwort=md5(passwort);
UPDATE personen SET alter=abs(-20), name=upper(name);

## CREATE TABLE

### Syntax

    CREATE TABLE tabellen_name (spalten_name  typ [DEFAULT 'defaultWert'] [, spalten_name2  typ2 [DEFAULT 'defaultWert'], ... ]) [;]

###
Unterstützt

- Siehe Syntax
- DEFAULT (Den Defaultwert in ' ' setzten, auch bei Zahlen)
- Wenn für eine inc Spalte ein Defaultwert gesetzt wurde, so sind die inc Werte des ersten
Datensatzes Defaultwert+1. Für alle weiteren Spalten wird der Defaultwert ignoriert.

### Nicht unterstützt

- Alles was nicht irgendwie unter Syntax zu finden ist !!
- Nur folgende Syntax (spalten_name typ , spalten_name typ , ....)
und sonst kein einiziges Keyword (ausser DEFAULT)!!
- SQL Standardtypen, typ kann nur inc (AutoWert), int (Zahl) oder str (Text) sein.

### Beispiel

CREATE TABLE personen (id inc, vorname str DEFAULT 'john' , nachname str);

## DROP TABLE

### Syntax

    DROP TABLE tabelle1 [, tabelle2, ...][;]

###
Unterstützt

- Siehe Syntax
- 1 oder mehrere Tabellen gleichzeitig löschen

### Nicht unterstützt

- Alles was nicht irgendwie unter Syntax zu finden ist !!

### Beispiel

DTOP TABLE personen;

## LIST TABLES

### Syntax

    LIST TABLES [WHERE ...]
    [GROUP BY spalten_name, ...]
    [ORDER BY spalten_name [ASC | DESC] ,...]
    [LIMIT [offset,]anzahl] [;]

###
Unterstützt

- Siehe Syntax
- Gibt alle Tabellen einer Datenbank als ResultSet Objekt zurück. Dieses ResultSet hat eine Spalte
Namens "table" welche den Tabellennamen als String enthält
- Für WHERE, GROUP BY, ORDER BY und LIMIT Syntax siehe SELECT

### Nicht unterstützt

- Alles was nicht irgendwie unter Syntax zu finden ist !!
- Funktionen

### Beispiel

LIST TABLES;

## CREATE DATABASE

### Syntax

    CREATE DATABASE datanbank_name [;]

###
Unterstützt

- Siehe Syntax
- Nur eine Databank kann mit einem Statement erzeugt werden.
- Dieses Statement sollte NUR auf einer ROOT_DATABASE Datanbank ausgeführt werden.
Man erhält diese mit einem $db=new Database(ROOT_DATABASE); aufruf.
ROOT_DATABASE ist eine definierte Konstante.

### Nicht unterstützt

- Alles was nicht irgendwie unter Syntax zu finden ist !!

### Beispiel

CREATE DATABASE meineDatenbank;

## DROP DATABASE

### Syntax

    DROP DATABASE datanbank_name [;]

###
Unterstützt

- Siehe Syntax
- Nur eine Databank kann mit einem Statement gelöscht werden.
- Dieses Statement sollte NUR auf einer ROOT_DATABASE Datanbank ausgeführt werden.
Man erhält diese mit einem $db=new Database(ROOT_DATABASE); aufruf.
ROOT_DATABASE ist eine definierte Konstante.

### Nicht unterstützt

- Alles was nicht irgendwie unter Syntax zu finden ist !!

### Beispiel

DROP DATABASE meineDatenbank;