# SQL Data Definition Language



## Wang (8. Nov 2011)

Hallo,

es wäre sehr nett, wenn sich jemand meine Lösung zu dieser Aufgabe ansehen könnte, da ich in SQL leider noch ein Newbie bin (Vorlesung: Datenbanken):







(a)


```
CREATE TABLE L
(
	lnr VARCHAR (10) ,
	lname VARCHAR (40) NOT NULL,
	sitz VARCHAR (40),
	PRIMARY KEY(lnr)
);

CREATE TABLE T
(
	tnr VARCHAR (10),
	tname VARCHAR (40) NOT NULL,
	farbe VARCHAR (40),
	gewicht INT,
	preis VARCHAR (40),
	PRIMARY KEY(tnr)
);

CREATE TABLE P
(
	pnr VARCHAR (10),
	pname VARCHAR (40) NOT NULL,
	ort VARCHAR (40),
	PRIMARY KEY(pnr)
);

CREATE TABLE LTP
(
	lnr VARCHAR (10),
	tnr VARCHAR (10),
	pnr VARCHAR (10),
	menge INT,
	PRIMARY KEY(lnr, tnr, pnr),
	FOREIGN KEY(lnr, tnr, pnr) references L(lnr), T(tnr), P(pnr) ON DELETE CASCADE ON UPDATE CASCADE
);
```

(b)


```
ALTER TABLE L ADD status INT;
```

(c)


```
ALTER TABLE T MODIFY preis FLOAT (2);
```

(d)


```
ALTER TABLE T DROP preis;
```

(e)


```
DROP TABLE L, T, P, LTP;
```


Ich danke Euch vielmals für Eure Hilfe und Mühe!

Gruß
Wang


----------



## faetzminator (8. Nov 2011)

Ich würde das einfach schnell in einer DB testen... Und da ich gerade keine zur Hand hab, hier eine Gegenfrage: Warum testest du das nicht mit einer laufenden DB  ?
Aber grundsätzlich kann ich keinen schwerwiegenden Fehler erkennen.


----------



## Wang (8. Nov 2011)

faetzminator hat gesagt.:


> Ich würde das einfach schnell in einer DB testen... Und da ich gerade keine zur Hand hab, hier eine Gegenfrage: Warum testest du das nicht mit einer laufenden DB  ?



Was bietet sich da am besten an; "Oracle Database 11g"?
Ich bin bzgl. SQL und Datenbanken leider der totale Newbie...



faetzminator hat gesagt.:


> Aber grundsätzlich kann ich keinen schwerwiegenden Fehler erkennen.



Die Aufgabenstellung gibt einem ja einigen Spielraum... würdest Du am Ende der (a) sagen, dass das mit dem FOREIGN KEY so in Ordnung ist?


```
CREATE TABLE LTP
(
    lnr VARCHAR (10),
    tnr VARCHAR (10),
    pnr VARCHAR (10),
    menge INT,
    PRIMARY KEY(lnr, tnr, pnr),
    FOREIGN KEY(lnr, tnr, pnr) REFERENCES L(lnr), T(tnr), P(pnr) ON DELETE CASCADE ON UPDATE CASCADE
);
```


----------



## chalkbag (8. Nov 2011)

Ja nimm einfach mal Oracle DB Express, mit schöner Installation, leichter Konfiguration und guten Informationen wo der SQL / die DDL falsch ist. Die Weboberfläche ist eigentlich wirklich ganz nett.

Oracle Database Express Edition 11g Release 2


----------



## Evil-Devil (8. Nov 2011)

Eine Spalte fügt man mit "alter table <tabellenname> add column <spaltenname> <typ> <zusätzliche optionen>" an.

Das sollte in nahezu allen aktuellen SQL DBMS identisch sein. Bei den Constraints weiß ich leider selbst nicht wie das abläuft. Ich kümmere mich um die Referenzielle Intigrität immer selbst.


----------



## Wang (8. Nov 2011)

Die Aufgabe wurde leider erweitert... Ich habe zwar die Lösung, kann sie aber nicht nachvollziehen - da hilft auch keine DB. Hier die Aufgabenstellung und Beispielrelationen, die die Bearbeitung erleichtern sollen:






Lösung:


```
SELECT DISTINCT tname,gewicht
FROM T,LTP LTP1,LTP LTP2
WHERE LTP1.pnr = ‘P1’
AND LTP2.pnr = ‘P2’
AND LTP1.tnr = T.tnr
AND LTP1.tnr = LTP2.tnr;
```


Fragen:
- Mir bereitet die Formulierung in Zeile 2 etwas Schwierigkeiten... Sind LTP1 und LTP2 einfach nur eine Art Zugriffsvariablen?
- Wozu dient die Zeile 5; damit werden doch alle Teilenummer aus LTP ausgegeben, die in der Relation T vorhanden sind, was doch total überflüssig ist?

Nochmals vielen Dank!


----------



## qowaz (8. Nov 2011)

Hinter FROM dürfen nur Tabellennamen stehen, laut deinem Beispiel gibt es aber keine Tabellen LTP1 und LTP2.


----------



## Evil-Devil (8. Nov 2011)

qowaz hat gesagt.:


> Hinter FROM dürfen nur Tabellennamen stehen, laut deinem Beispiel gibt es aber keine Tabellen LTP1 und LTP2.



LTP1 und LTP2 sind die Aliase die er definiert hat um LTP zweimal nutzen zu können!


----------



## faetzminator (8. Nov 2011)

Schreibt man da nicht noch [c]AS[/c] dazwischen? Dann ist auch klar, was gemeint ist... [c]FROM T, LTP AS LTP1, LTP AS LTP2[/c]


----------



## Evil-Devil (9. Nov 2011)

Das AS kann man in den meisten DMBS weglassen. Es erhöht lediglich die Lesbarkeit.

In dem Zusammenhang hatte ich zumindest unter SQL mal einen nervigen Bug. Sobald man dort für eine Tabelle einen Alias anlegt ist sie innerhalb des Queries ausschließlich über den Alias ansprechbar.

@Fragen: Na über Zeile 5 erhältst die den Zugriff auf den Namen deiner Teile. Ohne die Verbindung wäre die Verbindung nicht gegeben.


----------



## faetzminator (9. Nov 2011)

Evil-Devil hat gesagt.:


> In dem Zusammenhang hatte ich zumindest unter SQL mal einen nervigen Bug. Sobald man dort für eine Tabelle einen Alias anlegt ist sie innerhalb des Queries ausschließlich über den Alias ansprechbar.


Aber bei einer Abfrage wie [c]FROM T, LTP AS LTP1, LTP AS LTP2[/c], was soll denn da passieren, wenn ich auf [c]LTP[/c] zugreifen will  ?


----------



## Evil-Devil (9. Nov 2011)

faetzminator hat gesagt.:


> Aber bei einer Abfrage wie [c]FROM T, LTP AS LTP1, LTP AS LTP2[/c], was soll denn da passieren, wenn ich auf [c]LTP[/c] zugreifen will  ?



Im besagten Beispiel schmeißt MySQL einen Fehler, dass es die Tabelle LTP nicht kennt. Kann sein das es in einer der Unterversionen von 5.x.x inzwischen geändert wurde, aber auf unserem 5.x.x System hat man mit diesen Umstand zu leben. Wobei es an sich sogar einleuchtet, denn der Tabellenbezeichner wird für den Lebenszeitraum der Abfrage geändert.

War halt eine nervige Angelegenheit als man auf das Problem gestoßen ist und nicht wusste das es daran lag, dass MySQL eine Fehlermeldung schmeißt jene Tabelle würde nicht existieren.


----------



## Wang (9. Nov 2011)

Evil-Devil hat gesagt.:


> @Fragen: Na über Zeile 5 erhältst die den Zugriff auf den Namen deiner Teile. Ohne die Verbindung wäre die Verbindung nicht gegeben.



Leider leuchtet mir das noch nicht ein, obwohl ich schon eine gefühlte Ewigkeit vor diesem Code sitze... Ich gehe mal die Bedeutung der einzelnen Zeilen ab Zeile 3 durch:

Zeile 3: Selektion aller Zeilen aus LTP1, wo die Projektnummer P1 auftaucht
Zeile 4: Selekton aller Zeilen aus LTP2, wo die Projektnummer P2 auftaucht
Zeile 5: Selektion aller Zeilen aus LTP1, deren Teilenummern in der Relation T auftreten [nachdem die Relation T aber alle existierenden Teilenummern enthält, sind das doch gerade die Einträge, die man nach Zeile 3 erhält, sprich es werden hiermit keine Einträge aussortiert ???:L ]
Zeile 6: Selektion aller Zeilen, deren Teilenummern sowohl in LTP1 auftreten als auch in LTP2

Natürlich müssen diese Bedingungen alle gleichzeitig erfüllt sein, ich kann aber nicht verstehen, wozu die Zeile 5 gebraucht wird... Dann hätte man doch zusätzlich auch 
	
	
	
	





```
AND LTP2.tnr = T.tnr
```
 schreiben müssen ???:L


----------



## chalkbag (9. Nov 2011)

Blödsinn gelöscht


----------



## Evil-Devil (9. Nov 2011)

Wang hat gesagt.:


> Zeile 5: Selektion aller Zeilen aus LTP1, deren Teilenummern in der Relation T auftreten [nachdem die Relation T aber alle existierenden Teilenummern enthält, sind das doch gerade die Einträge, die man nach Zeile 3 erhält, sprich es werden hiermit keine Einträge aussortiert ???:L ]


Schau mal in deiner Select Zeile. Dort wird auf TName zugegriffen und die Spalte stammt aus T. Solange du keine passende Zuweisung zu T hast kann TName nicht ausgegeben werden. DEnn TName existiert nur in T und nirgendwo sonst


----------



## Wang (9. Nov 2011)

Evil-Devil hat gesagt.:


> Schau mal in deiner Select Zeile. Dort wird auf TName zugegriffen und die Spalte stammt aus T. Solange du keine passende Zuweisung zu T hast kann TName nicht ausgegeben werden. DEnn TName existiert nur in T und nirgendwo sonst



Macht man das der DB aber nicht bereits mit dem 
	
	
	
	





```
FROM T
```
 aus 
	
	
	
	





```
FROM T,LTP LTP1,LTP LTP2
```
 klar?


----------



## Evil-Devil (9. Nov 2011)

Nein.
Das FROM legt lediglich fest welche Tabellen abgefragt werden sollen. Wie die zusammenhängen musst du SQL mit auf den Weg geben.

Wenn du die Zeile 5 weglassen würdest, dann würdest du für jeden Eintrag in T einen Eintrag zu deinen Einträgen in LTP1 und LTP2 bekommen. Das willst du doch gar nicht 
Dich interessieren doch nur Teile die zu den Projekten gehören.

Denn woher soll SQL wissen das zb. T1 aus LTP1 zu T1 aus T gehört? Über die Referenzielle Intigrität könnte SQL das vermutlich annehmen, aber afaik greift die nur bei Insert/Update/Delete. Wie gesagt, hab die außer bei MS Access nie genutzt.

Ansonsten erstelle dir die Tabellen mit den entsprechenden Daten und probiere die Abfrage einmal mit und ohne Zeile 5 aus


----------



## Wang (9. Nov 2011)

Ich habe alle Tabellen in MySQL 5.5 eingegeben und mit sämtlichen Befehlen "gespielt" um mich mit der Materie besser vertraut zu machen. Allerdings erhalte ich nach Eingabe von 


```
SELECT DISTINCT tname,gewicht
FROM T,LTP LTP1,LTP LTP2
WHERE LTP1.pnr = ‘P1’
AND LTP2.pnr = ‘P2’
AND LTP1.tnr = T.tnr
AND LTP1.tnr = LTP2.tnr;
```

den folgenden Fehler:



> ERROR 1054 (42S22): Unknown column 'LTP.tnr' in 'where clause'



Weiß jemand woran das liegt?

EDIT:
Hat sich erledigt, nachdem ich den Command Line Client geschlossen und erneut gestartet habe... Ist nicht meine Woche...


----------

