mit sqlite einen zusammengehängten SELECT-Befehl

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
joefromthere
User
Beiträge: 4
Registriert: Donnerstag 25. Dezember 2014, 16:03

Hallo Leute,
bin neu in Python, habt erbarmen :cry:

Ich habe 2 Tabellen people und addressbook:

Code: Alles auswählen

CREATE TABLE `addressbook` (
	`aid`	INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
	`pid`	INTEGER,
	`address`	TEXT,
	`city`	TEXT,
	`stateProv`	TEXT,
	`postalCode`	INTEGER,
	FOREIGN KEY(pid) REFERENCES people(pid)
);


CREATE TABLE `people` (
	`pid`	INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
	`prefix`	TEXT,
	`firstName`	TEXT,
	`lastName`	TEXT,
	`suffix`	TEXT,
	`birthday`	TEXT,
	`primaryAddressTag`	INTEGER,
	FOREIGN KEY(primaryAddressTag) REFERENCES addressbook(aid)
);
Aus diesen möchte ich folgendes selektieren und ausgeben:
Hans Muster, Testweg 3, 7000 - TestCity

Wie geht das? mit einem zusammenhängenden SELECT-Befehl?

Danke für die Hilfe
Zuletzt geändert von Anonymous am Donnerstag 25. Dezember 2014, 16:17, insgesamt 1-mal geändert.
Grund: Quelltext in SQL-Code-Tags gesetzt.
BlackJack

@joefromthere: Wo liegt denn das Problem? Was hast Du ander Dokumentation vom `sqlite3`-Modul denn nicht verstanden, da wird doch gezeigt wie man SQL-Anfragen durchführt.

Ansonsten ist das ja eher eine SQL als eine Python-Frage. Und es riecht so ein bisschen danach als möchtest Du das jemand Deine SQL-Hausaufgaben für Dich lösen soll. ;-)

Das Ergebnis ist etwas ungenau angegeben. Die Datenbank enthält Vor- und Nachname als getrennte Felder, in Deinem Wunschergebnis sind die aber nur durch ein Leerzeichen getrennt, während das Komma als Feldtrenner zu fungieren scheint. Ausser bei den letzten beiden Werten — da steht dann ein Minus/Bindestrich. Sollen da also Felder aus den Tabellen im Ergebnis per SQL schon zu einem zusammengefasst werden, oder wie? Und was davon soll eigentlich das Suchkriterium sein? Denn ansonsten könnte man auch völlig unabhängig von den Tabellendeklarationen folgende ”Lösung” als SQL-Abfrage vorschlagen:

Code: Alles auswählen

sqlite> SELECT "Hans Muster, Testweg 3, 7000 - TestCity";
Hans Muster, Testweg 3, 7000 - TestCity
Ich habe aber so das Gefühl dafür gäbe es keine Punkte.

Beim DB-Entwurf würde ich `people` eher `person` nennen. `people` ist Mehrzahl und eher in der Bedeutung von „Volk” wie in „we the people” → „wir das Volk”, oder „the people vs. Omnicorp” → „das Volk gegen Omnicorp”. Die Postleitzahl ist keine Zahl vom Typ her. Es gibt welche das sind führende 0en wichtig und es gibt auch Länder das sind auch Buchstaben im „postal code” enthalten. Oder Leerzeichen, Bindestriche oder andere Sonderzeichen.
joefromthere
User
Beiträge: 4
Registriert: Donnerstag 25. Dezember 2014, 16:03

@BlackJack
Ich glaube du hast mich falsch verstanden,
ich möchte alle einträge, welche ich in der Datenbank drin habe eine Abfrage machen,
wobei firstname lastname address postalCode und city angezeigt wird.
Bei all dem habe ich vergessen zu sagen, dass der primaryAddressTag die erstaddresse ist welche er eben aus addressbook holen soll.

z B Tabelle people
(pid)1 (firstName) Hans (lastName) Muster (primaryAddressTag) 1

Tabelle addressbook
(aid) 1 (pid) 1 (address) testweg 2 (city) zürich (postalCode) 8321
(aid) 2 (pid) 1 (address) testweg 3 (city) Basel (postalCode) 8541

Dann soll er mir folgendes Ausgeben

Hans Muster testweg 2 (da aid der primaryAddressTag ist 1=1) 8321 zürich
BlackJack

@joefromthere: Und wo hast Du jetzt das konkrete Problem? Das sind Grundlagen von relationalen Datenbanken bzw. SQL. Was benutzt Du denn zum Lernen davon?
joefromthere
User
Beiträge: 4
Registriert: Donnerstag 25. Dezember 2014, 16:03

Sieh, hier hab ich meinen Code.
Ich habe keine Ahnung, ob ich für beide Tabellen eine einzelne Abfrage machen , und die irgendwie miteinander vergleichen muss,
um meinen Datensatz zu bekommen, in dem die Person und die Adresse, von den verschiedenen Tabellen herauskriege.
ALLE personen sollten ausgegeben werden, natürlich mit ihren wohnorten. der primaryaddresstag ist der erste, also der in diesem Fall
zu nutzenden Wohnort, der gesucht werden und zusammen mi dem Wohnort ausgegeben muss.

Code: Alles auswählen

import sqlite3, sys

try:
    connection = sqlite3.connect("Adressen.db")  #Datenbankverbindung als Variable
    cursor = connection.cursor() 
    
    cursor.execute("SELECT * FROM people ")
    data = cursor.fetchall()
    for datarow in data:
        print data
        pid, prefix, firstName, lastName, suffix, birthday, primaryAddressTag = datarow
        test = primaryAddressTag
        cursor.execute("SELECT address, postalCode, city FROM addressbook WHERE aid=?", str(test))
        test2 = cursor.fetchall()
        print test2


except sqlite3.Error, e:
    
    print "Error %s:" % e.args[0]
    sys.exit(1)
    
finally:
    
    if connection:
        connection.close()
Zuletzt geändert von Anonymous am Donnerstag 25. Dezember 2014, 18:52, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@joefromthere: Das zweite Argument von `Cursor.execute()` muss eine Sequenz von Werten sein. Was Du Da machst kann eventuell bei SQLite funktionieren solange `test` einstellig bleibt, ist aber falsch. Eben weil es auf die Nase fällt sobald die ID an der Stelle grösser als 9 wird.

Man würde so etwas auch nicht in Python mit einer Abfrage pro Personendatensatz machen sondern *eine* SQL-Abfrage schreiben welche die gewünschten Daten selektiert. Wie gesagt das SQL-Grundlagen. Such Dir da mal ein Tutorial das Du durcharbeiten kannst. Es gibt zum Beispiel ein Wikibook, oder Learn SQL The Hard Way. Letzteres ist zwar noch nicht vollendet, aber das was schon vorhanden ist, deckt Deinen einfachen Fall schon ab.

``SELECT * FROM …`` macht man üblicherweise nicht, denn damit erhält man Code der von der Anzahl und Reihenfolge der Tabellenspalten abhängig ist. Wenn man daran später einmal Veränderungen vornehmen muss, dann muss man auch alle Codestellen ändern. Wenn man die Reihenfolge der Spalten in der Datenbank ändert, oder neue Spalten hinzufügt, dann muss man am Code nichts ändern wenn man dort im SELECT explizit aufgelistet hätte welche Spalten und damit auch in welcher Reihenfolge man in der Ergebnismenge haben möchte.

Die Zuweisung ``test = primaryAdressTag`` ist überflüssig und `test2` ist kein guter Name.

Die Fehlerbehandlung ist ungünstig. Wenn man an der Stelle das Programm sowieso abbricht kann man es auch ganz sein lassen mit dem ``except`` und hat dann sogar noch mehr Informationsausgabe über das Problem.

Der Code im ``finally``-Zweig ist fehlerhaft denn wenn beim `connect()`-Aufruf eine Ausnahme ausgelöst wird, dann ist der Name `connection` nicht definiert und das ``if`` im ``finally`` führt zu einem `NameError`. Sollte der `connect()`-Aufruf funktionieren, dann ist diese ``if``-Bedingung *immer* wahr. Das ``if`` macht also absolut keinen Sinn an der Stelle.
joefromthere
User
Beiträge: 4
Registriert: Donnerstag 25. Dezember 2014, 16:03

@BlackJack
Vielen Dank für deine Bemühungen, ich werde da mal reinschauen:)

Schöne Tage und nochmals Danke
Antworten