Mehrere Tabellen verknüpfen

Mehrere Tabellen verknüpfen

am 16.02.2007 11:56:09 von Michael Koch

Hallo,

ich mach jetzt schon ne geraume Zeit an einem Problem rum an dem ich
einfach nicht weiterkomme :-(. Deswegen will ich hier al nachfragen.

Also: Ich habe eine SQL - DB mit folgenden Tabellen: Kurskarte,
Seminarteilnehmer und Veranstaltung (natürlich sind da auch noch andere
aber die sind hier nicht relevant :-) ). Es ist so daß sich Leute eine
Kurskarte zulegen können und sich damit an die Seminare anmelden können.
Nachdem dann die Kurskarten alle vergeben sind können sich die einzelnen
Teilnehmer an den Seminaren mit hilfe ihrer Kurskartennummer anmelden.
Soweit so gut. Nun sollen eine Woche vor dem Seminar nochmal alle
Kurskartenbesitzer angeschrieben werden, die sich noch nicht angemeldet
haben (also alle die eine Kurskarte haben, deren Kurskarte aber nicht mit
der Nr. und der Veranstaltung in der Tabelle Teilnehmer stehen). Und genau
hier habe ich ein Problem. Irgendwie komme ich immer nur aif die die sich
schon angemeldet haben, aber ich brauche es genau anderst herum :-). Ich
poste mal den Code den ich mal so zusammengestrickt habe



$sql_rcpt = "SELECT * FROM kurskarten WHERE jahrgang = " .$jahrgang;
while ($sqlarray = mysql_fetch_array($query))
{
$inner_sql = "SELECT * FROM teilnehmer WHERE Veranstaltung = ".$_POST
["pVID"]." AND Kurskarte = ".$sqlarray['KKNummer'];
$inner_query = mysql_query($inner_sql) or die("Anfrage war nicht
erfolgreich. War ja klar :-(.");
while ($inner_sqlarray = mysql_fetch_array($inner_query))
{
echo $sqlarray['Mail']."
";
}


Kann mir vielleicht jemand auf die Sprünge helfen? Es ist wohl nix Großen,
aber ich komme einfach nicht auf die Lösung. Ich denke man müsste nur ein
SQL Statement ändern. Aber wie :-)?

Danke

Michael

Re: Mehrere Tabellen verknüpfen

am 16.02.2007 12:01:31 von Florian Laws

On 2007-02-16, Michael Koch wrote:
> Hallo,
>
> ich mach jetzt schon ne geraume Zeit an einem Problem rum an dem ich
> einfach nicht weiterkomme :-(. Deswegen will ich hier al nachfragen.
>
> Also: Ich habe eine SQL - DB mit folgenden Tabellen: Kurskarte,
> Seminarteilnehmer und Veranstaltung

Bitte poste die Tabellendefinitionen,
ggf. mit Erklärung der Bedeutung der Felder.

Grüße,

Florian

Re: Mehrere Tabellen verknüpfen

am 16.02.2007 12:16:02 von Michael Koch

Hallo Florian,

Florian Laws wrote:

> Bitte poste die Tabellendefinitionen,
> ggf. mit Erklärung der Bedeutung der Felder.

Hier, bitte. Die Kommentare habe ich nun nur an die wichtigen
drangeschrieben.

CREATE TABLE `kurskarten` (
`KID` int(11) NOT NULL auto_increment,
`Firma` varchar(255) NOT NULL,
`Titel` int(2) NOT NULL,
`Name` varchar(255) NOT NULL,
`Vorname` varchar(255) NOT NULL,
`Strasse` varchar(255) NOT NULL,
`PLZ` int(5) NOT NULL,
`Ort` varchar(255) NOT NULL,
`Telefon` varchar(20) NOT NULL,
`Fax` varchar(20) default NULL,
`Mail` varchar(255) NOT NULL, //Das ist die Mailaddresse die ich will
`Anzahl` int(2) NOT NULL,
`Ermaessigung` int(2) NOT NULL,
`IP` varchar(20) NOT NULL,
`AnmeldeDatum` date NOT NULL,
`KKNummer` int(10) NOT NULL, //KurskartenNummer
`jahrgang` int(4) NOT NULL, //Das Jahr für das die Karte gültig ist
`Hausnummer` varchar(5) NOT NULL,
`Kontigent` tinyint(4) NOT NULL default '3',
`gedruckt` tinyint(4) NOT NULL default '0',
`Passwort` varchar(50) NOT NULL,
`Typ` int(1) NOT NULL default '0',
PRIMARY KEY (`KID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;

CREATE TABLE `teilnehmer` (
`ID` int(11) NOT NULL auto_increment,
`Name` varchar(50) NOT NULL, //Die werden gebraucht, da sich
`Vorname` varchar(50) NOT NULL, //jeweils 3 P pro Karte anmelden
`Titel` int(11) NOT NULL, //können
`Mail` varchar(50) NOT NULL,
`Firma` varchar(50) NOT NULL,
`AnmeldeDatum` date NOT NULL,
`AnmeldeIP` varchar(15) NOT NULL,
`Veranstaltung` int(2) NOT NULL, //hier steht die VeranstaltungsID
`Anrede` int(1) NOT NULL,
`Ort` varchar(50) NOT NULL,
`gedruckt` tinyint(1) NOT NULL default '0',
`Kurskarte` int(5) NOT NULL default '0', //hier steht die KKNummer
`sp_Strasse` varchar(255) default NULL, //Die sind für Einzelkarten
`sp_Hausnummer` varchar(50) default NULL,//
`sp_Fon` varchar(25) default NULL, //
`sp_Fax` varchar(25) default NULL, //
`sp_Plz` varchar(10) default NULL, //
`sp_Group` int(1) NOT NULL default '0', //
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;

CREATE TABLE `veranstaltung` (
`VID` int(11) NOT NULL auto_increment, //Die ID die in teilnehmer steht
`Veranstaltung` varchar(255) NOT NULL,
`Veranstaltungsdetails` varchar(50) default NULL,
`Veranstaltungdatum` date NOT NULL,
`Aktiv` tinyint(1) NOT NULL,
`RaumNummer` varchar(20) NOT NULL,
`Zeit` varchar(11) NOT NULL,
`Programm` tinyint(1) default '0',
`Bemerkungen` varchar(1024) default NULL,
`Jahrgang` int(4) NOT NULL default '2006',
`Quota` int(2) NOT NULL default '0',
PRIMARY KEY (`VID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=16 ;


Ne Idee? Danke

Michael

Re: Mehrere Tabellen verknüpfen

am 16.02.2007 12:43:03 von Florian Laws

On 2007-02-16, Michael Koch wrote:
> Hallo Florian,
>
> Florian Laws wrote:
>
>> Bitte poste die Tabellendefinitionen,
>> ggf. mit Erklärung der Bedeutung der Felder.
>
> Hier, bitte. Die Kommentare habe ich nun nur an die wichtigen
> drangeschrieben.
>

SELECT Mail
FROM kurskarten
WHERE jahrgang =
AND KKNummer NOT IN (
SELECT KKNummer
FROM teilnehmer, veranstaltung
WHERE teilnehmer.Veranstaltung = veranstaltung.VID
AND veranstaltung.VID = )

Das gibt Dir erst eine Liste der Kurskartennummern der Leute,
die an der gewünschten Veranstaltung teilnehmen,
und sucht anschliessend alle Kurskarten des gewünschten Jahrgangs
heraus, die nicht auf dieser Liste stehen.

Mir sind übrigens noch ein paar Dinge aufgefallen:

- Du solltest Deine SQL-Statements nicht direkt mit Daten aus
GET- oder POST-Parametern füttern, ohne zu prüfen, dass nur
erwartete Werte drinstehen und sie zu quoten.
Sonst können böse Benutzer Deiner Datenbank beliebige
Befehle unterschieben und u.U. die Kontrolle über Deinen
Server bekommen (das Problem nennt man SQL Injection)
- Warum haben Kurskarten sowohl eine KID als auch eine KKNummer?
- Die Datentypen von Feldern, die zusammengehören, sollten eigentlich
nicht unterschiedlich sein:
KKNummer ist INT(10) in kurskarten
aber Kurskarte ist INT(5) in teilnehmer
ebenso ist
Veranstaltung INT(2) in teilnehmer
aber VID ist int(11) in veranstaltung


Ich würde Dir empfehlen, mal ein, zwei gute Bücher über
SQL und über Sicherheit beim PHP-Programmieren zu lesen. :)

Grüße,

Florian

Re: Mehrere Tabellen verknüpfen

am 16.02.2007 12:46:24 von Florian Laws

On 2007-02-16, Florian Laws wrote:
> On 2007-02-16, Michael Koch wrote:
>> Hallo Florian,
>>
>> Florian Laws wrote:
>>
>>> Bitte poste die Tabellendefinitionen,
>>> ggf. mit Erklärung der Bedeutung der Felder.
>>
>> Hier, bitte. Die Kommentare habe ich nun nur an die wichtigen
>> drangeschrieben.
>>
>
> SELECT Mail
> FROM kurskarten
> WHERE jahrgang =
> AND KKNummer NOT IN (
> SELECT KKNummer
> FROM teilnehmer, veranstaltung
> WHERE teilnehmer.Veranstaltung = veranstaltung.VID
> AND veranstaltung.VID = > )

Ach murks, es muss natürlich heissen:

SELECT Mail
FROM kurskarten
WHERE jahrgang =
AND KKNummer NOT IN (
SELECT teilnehmer.Kurskarte AS KKNummer
FROM teilnehmer, veranstaltung
WHERE teilnehmer.Veranstaltung = veranstaltung.VID
AND veranstaltung.VID =
)


Das kommt davon, wenn man unterschiedliche Feldnamen für die
gleiche Sache hat.

Grüße,

Florian

Re: Mehrere Tabellen verknüpfen

am 16.02.2007 13:06:14 von Michael Koch

Hi Florian,

> SELECT Mail
> FROM kurskarten
> WHERE jahrgang =
> AND KKNummer NOT IN (
> SELECT KKNummer
> FROM teilnehmer, veranstaltung
> WHERE teilnehmer.Veranstaltung = veranstaltung.VID
> AND veranstaltung.VID = > )


Danke, das scheint zu funktionieren :-). Zumindest die zweite Variante.

> - Du solltest Deine SQL-Statements nicht direkt mit Daten aus
> GET- oder POST-Parametern füttern, ohne zu prüfen, dass nur
> erwartete Werte drinstehen und sie zu quoten.
> Sonst können böse Benutzer Deiner Datenbank beliebige
> Befehle unterschieben und u.U. die Kontrolle über Deinen
> Server bekommen (das Problem nennt man SQL Injection)

Mach ich ja normalerweise. Der Code war jetzt zum ausprobieren. Und da
wollte ich mich nicht noch mit meinen Fehlern in der überprüfung
rumärgern :-).

> - Warum haben Kurskarten sowohl eine KID als auch eine KKNummer?

Das war eine Vorgabe, daß die Nummern nicht aufeinanderfolgend sind und
auch ein bestimmtes Format haben.

> - Die Datentypen von Feldern, die zusammengehören, sollten eigentlich
> nicht unterschiedlich sein:
> KKNummer ist INT(10) in kurskarten
> aber Kurskarte ist INT(5) in teilnehmer
> ebenso ist
> Veranstaltung INT(2) in teilnehmer
> aber VID ist int(11) in veranstaltung

Ja, ich weiß :-(. Das wollte ich schon lange ändern. Irgendwie vergesse
ich das immer. Aber jetzt ist es geändert :-).

> Ich würde Dir empfehlen, mal ein, zwei gute Bücher über
> SQL und über Sicherheit beim PHP-Programmieren zu lesen. :)

Nun, schaden würde es bestimmt nicht :-). Werde ich mir mal ein paar in
der Bib ausleihen. Kannst du welche empfehlen?

Also, danke nochmal. Gruß und ein schönes Wochenende.

Michael

Re: Mehrere Tabellen verknüpfen

am 16.02.2007 13:16:58 von Claus Reibenstein

Michael Koch schrieb:

> Florian Laws wrote:
>
>> Bitte poste die Tabellendefinitionen,
>> ggf. mit Erklärung der Bedeutung der Felder.
>
> Hier, bitte. Die Kommentare habe ich nun nur an die wichtigen
> drangeschrieben.
>
> CREATE TABLE `kurskarten` (
> [...]
> `Mail` varchar(255) NOT NULL, //Das ist die Mailaddresse die ich will
> [...]
> `KKNummer` int(10) NOT NULL, //KurskartenNummer
> ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
>
> CREATE TABLE `teilnehmer` (
> [...]
> `Veranstaltung` int(2) NOT NULL, //hier steht die VeranstaltungsID
> [...]
> `Kurskarte` int(5) NOT NULL default '0', //hier steht die KKNummer
> [...]
> ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
>
> CREATE TABLE `veranstaltung` (
> `VID` int(11) NOT NULL auto_increment, //Die ID die in teilnehmer steht
> [...]
> ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=16 ;

SELECT Mail FROM kurskarten k
LEFT JOIN teilnehmer t on k.KKNummer = t.Kurskarte
LEFT JOIN veranstaltung v on t.Veranstaltung = v.VID
WHERE t.Veranstaltung IS NULL;

Oder so ähnlich (nicht getestet!).

Gruß. Claus
--
,~°O O
O ,´ / |/|\
/ |¯`. Das neue Hochzeits-Branchenbuch im Internet ,´ / | |\
/__| `~...............................................~´ /___|/ /

Re: Mehrere Tabellen verknüpfen

am 16.02.2007 14:09:04 von Joerg Behrens

Michael Koch schrieb:

>> Ich würde Dir empfehlen, mal ein, zwei gute Bücher über
>> SQL und über Sicherheit beim PHP-Programmieren zu lesen. :)
>
> Nun, schaden würde es bestimmt nicht :-). Werde ich mir mal ein paar in
> der Bib ausleihen. Kannst du welche empfehlen?

Das da!
http://www.amazon.de/PHP-Sicherheit-PHP-MySQL-Webanwendungen -sicher-programmieren/dp/3898643697

Die beiden arbeiten allerdings an einer weiteren Auflage welches dann
auch Ext/Filter mit einschliesst.

Gruss
Joerg

--
TakeNet GmbH, Geschaeftsfuehrer Wolfgang Meier
97080 Wuerzburg Tel: +49 931 903-2243
Alfred-Nobel-Straße 20 Fax: +49 931 903-3025
HRB Wuerzburg 6940 http://www.takenet.de

Re: Mehrere Tabellen verknüpfen

am 16.02.2007 19:55:01 von Florian Laws

On 2007-02-16, Claus Reibenstein <4spammersonly@web.de> wrote:
> Michael Koch schrieb:
>
>
> SELECT Mail FROM kurskarten k
> LEFT JOIN teilnehmer t on k.KKNummer = t.Kurskarte
> LEFT JOIN veranstaltung v on t.Veranstaltung = v.VID
> WHERE t.Veranstaltung IS NULL;

Wenn ich die Frage richtig verstanden habe, gibt es keine
Teilnehmer-Einträge für Kurskarten, die nicht an einer Veranstaltung
teilnehmen, auch keine, deren Veranstaltungs-Feld NULL ist.

Grüße,

Florian

Re: Mehrere Tabellen verknüpfen

am 16.02.2007 20:57:55 von Helmut Chang

Florian Laws schrieb:

>> SELECT Mail FROM kurskarten k
>> LEFT JOIN teilnehmer t on k.KKNummer = t.Kurskarte
>> LEFT JOIN veranstaltung v on t.Veranstaltung = v.VID
>> WHERE t.Veranstaltung IS NULL;
>
> Wenn ich die Frage richtig verstanden habe, gibt es keine
> Teilnehmer-Einträge für Kurskarten, die nicht an einer Veranstaltung
> teilnehmen, auch keine, deren Veranstaltungs-Feld NULL ist.

Genau. Und in so einem Fall ist bei einem LEFT (OUTER) JOIN rechts alles
NULL und die WHERE-Bedingung trifft zu.

gruss, heli