sqlite insert list into row

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

Hallo!

ich versuche gerade meine Songs in einer eigenen Datenbank zu organisieren, aus Neugier möchte ich versch. Tabellen haben, die aus versch. Charts die Positionen speichert, diese Tabelle erstelle ich so:

Code: Alles auswählen

db_conn.execute("""CREATE TABLE IF NOT EXISTS br3 (
                           id INTEGER PRIMARY KEY,
                           kw INTEGER,
                           year INTEGER,
                           r_1 INTEGER,
                           r_2 INTEGER,
                           r_3 INTEGER,
                           FOREIGN KEY(r_1) REFERENCES tracks(id),
                           FOREIGN KEY(r_2) REFERENCES tracks(id),
                           FOREIGN KEY(r_3) REFERENCES tracks(id)""")
# es geht teilweise bis r_40
Nun habe ich eine Liste mit den Foreign Keys generiert und frage mich, wie ich den INSERT mache:
- mit Hilfe der Liste einen INSERT-String zusammenbasteln?
- mit einem Insert nur einen Teil (id, kw, year) der erstellen, dann über die Liste iterieren und jeweils einen UPDATE
machen?
- ich könnte mir auch vorstellen, dass jemand sowas schon mal versucht hat, es dafür eine Funktion im '
sqlite3-Modul gibt und ich sie nur nicht finden kann?
Welchen Ansatz würdet ihr wählen? Evtl ist auch das Tabellen-Design verbesserbar?

Viele Grüße,
Werner
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Merke: Wenn du anfängst Namen zu nummerieren, dann begehst du häufig einen Fehler. Wenn du versuchst einen Namen mit 40 verschiedenen Indizes zu erzeugen, dann begehst du mit absoluter Sicherheit einen Fehler ;-)

Dein Datenbankschema ist hier falsch. Unschön wird es doch schon bei Charts mit unterschiedlicher Länge (werden dann die letzten 10 mit NULL aufgefüllt?) oder wenn du die Länge der Charts verändern möchtest. Du willst eigentlich eine Tabelle mit den Einträgen Kalenderwoche (warum kürzt du das mit "kw" ab, sonst ist auch alles Englisch?), Jahr, Platzierung, ChartID und Titel. Wobei die letzten beiden Einträge natürlich Fremdschlüssel auf andere Tabellen sind.
Das Leben ist wie ein Tennisball.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@mcdwerner: So ganz verstehe ich deine Fragen nicht, denn ich weiß nicht, was r_1/2/3 bedeuten soll, oder was br3 (Bayrischer Rundfunk?). Aber guckstu hier, vielleicht beantwortet es wenigstens einen Teil deiner Fragen.
In specifications, Murphy's Law supersedes Ohm's.
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

@EyDu: ich hatte ja schon vermutet, dass es am Design liegt -> falls jemand einen guten Lesetip zum Thema Normalisierung hat, immer her damit! Vermutlich wollte ich instinktiv die n zu m Beziehung "ChartID - Titel" vermeiden ;-) wenn mir jemand die Beziehung, so wie Du, "vor die Füße wirft", dann sehe ich sie gleich. Nur von alleine meistens nicht, wahrscheinlich fehlt mir die Erfahrung...
@pillmuncher: danke für den Link! executemany() hätte dann der "UPDATE-Lösung" entsprochen
r_1 hat in meinem Plan der Chart-Platzierung "Rang/k" entsprochen und br3 heisst tatsächlich "Bayern3"
Danke schön :D
Werner
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@mcdwerner: Erstelle Dir ein ER-Diagramm vom Problem. Für die Wandlung existieren einfache Regeln, nach denen Du automatisch eine normalisierte DB in der dritten NF bekommst :-)

Du kannst das auf Papier machen, ansonsten nehme ich gerne "dia" dazu.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

... und schon hab ich wieder einen Knoten im Hirn (wie meistens beim Erstellen eines ER-Diagramms):
sind ("Bayern3 Schlager der Woche" -> "Track xy Platz 1 am 21.9.2012") oder ("Bayern 3 Schlager der Woche vom 21.9.2012" -> "Track xy Platz 1") die geeigneten Entities, oder anders ausgedrückt: kommt das Datum zum Track in die Detail-Tabelle oder erstelle ich jede Woche eine neue Zeile in der Chart-Tabelle?
Oder ist es einfach Geschmackssache???
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du musst dir nur die richtigen Fragen stellen: Gehört das Datum zu einem Track oder nicht? Dann solltest du recht schnell feststellen, dass das Datum keine Eigenschaft des Tracks ist, zumal zu einem einzelnen Track theoretisch beliebig viele Datumseinträge gehören könnten.

Mal so als Grundlage:

INTERPRETEN: Id, Name
TRACKS: Id, REF(INTERPRETEN.Id), Titel
SENDER: Id, Name
CHARTS: Id, REF(TRACKS.Id), REF(SENDER.Id), Datum, Platz
Das Leben ist wie ein Tennisball.
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

@EyDu: Dass das Datum keine Eigenschaft des Tracks ist, ist klar.
Ich habe zwischen Charts und Tracks eine n zu m Beziehung, da ich verschiedene Charts verwalten möchte und ein Track in mehreren Charts stehen kann. Die Frage war: kommt das Datum in diese Detail-Tabelle zum Fremdschlüssel Track und ich hab in der Charts-Tabelle tatsächlich nur die Namen der Charts oder ich packe das Datum in die Charts-Tabelle und ich erstelle hier jede Woche eine neue Zeile.
hier mal die möglichen CREATES:
Möglichkeit 1:
hier muss ich jede Woche einen neuen Eintrag in der Tabelle charts machen
kleiner Vorteil fällt mir gerade noch auf: week und year wird nicht redundant gespeichert

Code: Alles auswählen

"""CREATE TABLE IF NOT EXISTS charts (id INTEGER PRIMARY KEY,
                                      name TEXT,
                                      week INTEGER,
                                      year INTEGER)"""

    
"""CREATE TABLE IF NOT EXISTS chart_detail (id INTEGER PRIMARY KEY,
                                            chart INTEGER,
                                            position INTEGER,
                                            track INTEGER,
                                            FOREIGN KEY(track) REFERENCES tracks(id),
                                            FOREIGN KEY(chart) REFERENCES charts(id))"""
Möglichkeit 2:
hier muss ich immer nur chart_detail updaten (ausser ich nehme noch eine Hitparade dazu)

Code: Alles auswählen

"""CREATE TABLE IF NOT EXISTS charts (id INTEGER PRIMARY KEY,
                                      name TEXT)"""

    
"""CREATE TABLE IF NOT EXISTS chart_detail (id INTEGER PRIMARY KEY,
                                            chart INTEGER,
                                            position INTEGER,
                                            track INTEGER,
                                            week INTEGER,
                                            year INTEGER
                                            FOREIGN KEY(track) REFERENCES tracks(id),
                                            FOREIGN KEY(chart) REFERENCES charts(id))"""
Edith says: "mach die Formatierung g'scheit!"
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ok, da habe ich dich offensichtlich falsch verstanden. Aber auch bei deiner jetzigen Situation musst du überlegen, ob das Datum zu einem Chart (ich nenne das Singular mal Ranking, dann kommt man nicht so durcheinander) gehört oder nicht. Handelt es sich wirklich um ein komplett anderes Ranking, nur weil sich das Datum geändert hat? Ich würde sagen, dass dem nicht so ist, da der Sender (oder was auch immer) gleich bleibt. Also gehört das Datum zu einem Ranking, die zweite Möglichekeit würde ich daher eindeutig bevorzugen.

Bei dir kommt jetzt noch hinzu, dass du das Datum in Jahr und Woche unterteilen möchtest und nicht einfach nur als Datum. Wenn du es also wirklich normalisiert haben möchtest, dann müsstest du noch eine Tabelle für das Datum erstellen, welche dann aus der chart_detail-Tabelle referenziert wird.

Edit: Möglich ist natürlich auch ein Zwischenschritt:

CHARTS: Id, Name
RANKINGS: Id, REF(CHARTS.Id), Datum
CHART_DETAILS: ID, REF(RANKINGS.ID), ...

Die Lösung scheint mir besser zu sein als mein ursprünglicher Vorschlag. Ich sehe zumindest keine Redundanzen mehr. Vielleicht wills ja jemand genau nachprüfen ;-)
Das Leben ist wie ein Tennisball.
mcdwerner
User
Beiträge: 113
Registriert: Donnerstag 7. Juli 2011, 14:27

@EyDu: ich hatte auch schon den Verdacht, dass das Datum (oder besser die "Wertungswoche") eigentlich ausgelagert werden sollte.
Ich werd's jetzt so umsetzen und wenn die Abfragen komplexer werden hilft mir das nur beim Lernen ;-)

Vielen Dank!
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

je nach dem, was man wie abfragen will, liest sich auch eine NoSQL-Lösung hierfür gut einsetzen. Wie gesagt, je nach Abfragewünschen geht das sowohl per KV-Store also auch per Dokumenten-Orientierter DB.

Gruß, noisefloor
Antworten