Datenfeld mit For befüllen

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
NewPython19

Hallo :wink:

Ist es mit Sqlite3 in Python möglich, ein Datenfeld einer Datenbank über eine Schleife zu befüllen?

Ich möchte zum Beispiel in ein bestimmtes Datenfeld meines Datensatzen für jeden Datensatz in meiner Datenbank einen Wert eintragen.
Zu Beginn möchte ich im ersten Feld eine 1, im zweiten Feld eine 2 usw. stehen haben.
Ist das möglich?

Bisher habe ich mir folgendes überlegt (Ich weiß, dass ist nicht korrekt aber sowas in der Art stelle ich mir vor):

Code: Alles auswählen

    os.chdir(directory)
    connection = sqlite3.connect(database)
    cursor = connection.cursor()
    for row in cursor:
    sqlClientID = """INSERT INTO Data(Number) VALUES (i) """
    cursor.execute(sqlClientID)
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@NewPython19: warum sollte sqlite3 magisch as `i` im String durch eine Zahl, `Number` aber nicht ersetzen?

Statt dessen gibt es dafür Platzhalter:

Code: Alles auswählen

cursor.execute("INSERT INTO Data(Number) VALUES (?)", [i])
Der Code macht so keinen Sinn, `i` ist gar nicht definiert, `cursor` hat nichts, worüber er iterieren könnte, die Einrückungen sind falsch und `os.chdir` sollte in einem sauberen Programm nicht vorkommen. Pfade gibt man entweder relativ zum Arbeitsverzeichnis an, oder absolut.
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@NewPython19: Möchtest Du neue Datensätze erstellen oder bestehende verändern? Der Code scheint ja über ein Abfrageergebnis zu itererieren, aber da fehlt die SQL-Anweisung für die Abfrage. Und innerhalb der Schleife werden dann versucht Datensätze zu erstellen.

Der Name für das SQL-Fragment ist `sqlClientID` – was ist das für eine ID? IDs für Fremdschlüssel lässt man in der Regel die Datenbank selbst erzeugen. Selbst wenn man in den Daten IDs von ”aussen” hat, verwenden Viele trotzdem zusätzlich eine künstliche ID als Primärschlüssel.

Das `i` in dem SQL sollte ein Platzhalter sein, der dann über das zweite Argument der `execute()`-Methode mit einem Wert versorgt wird.

Das `os.chdir()` vergiss bitte mal gleich wieder. Zumal das hier überhaupt keinen Sinn macht. Dieser Aufruf verändert globalen Zustand. Das skaliert nicht und kann bei Fehlern problematisch werden.

Namen schreibt man in Python klein_mit_unterstrichen. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
NewPython19

Danke erstmal für die schnellen Antworten :)

1. ich hab gesagt, dass mein Code nicht richtig ist ;)

2. ich benutze das os.chdir(directory), weil meine Datenbank in einem bestimmten Verzeichnis erstellt ist. Was gibt es da für eine andere Möglichkeit, um den richtigen Pfad für die Datenbank zu errreichen/anzugeben?

3. Also muss ich das 'i' durch das (?) ersetzen? und wie binde ich das (?) in mein Programm ein? Kann ich das einfach anstelle von 'i' verwenden?

4. Mit der ID möchte ich sozusagen die Position des Datensatzes in der Datenbank bzw. Eingabereihenfolge angeben. Wenn ich es richtig verstanden habe, kann die auch automatisch erstellt werden?
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Hast Du eigentlich meinen Beitrag gelesen? Da sind alle Deine Fragen beantwortet.
Zu 4: Wenn ein Feld als `INTEGER PRIMARY KEY` typisiert ist, dann geht das automatisch.
NewPython19

Ich hab deinen Beitrag gelesen.
Ich hab doch nur nochmal nachgefragt
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wenn das wirklich die Eingabereihenfolge widerspiegeln soll, braucht man noch AUTOINCREMENT. Sonst können kleinere IDs wiederverwendet werden wenn Datensätze gelöscht werden. Das hat aber auch Nachteile/Kosten. Nachzulesen in der SQLite-Dokumentation: https://sqlite.org/autoinc.html
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
__deets__
User
Beiträge: 14542
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn du mit

Code: Alles auswählen

os.chdir(directory)
connection = sqlite3.connect(database)
ans Ziel kommst, dann kommst du auch mit

Code: Alles auswählen

connection = sqlite3.connect(os.path.join(directory, database))
dahin.
NewPython19

__blackjack__ hat geschrieben: Dienstag 23. Juli 2019, 10:20 Wenn das wirklich die Eingabereihenfolge widerspiegeln soll, braucht man noch AUTOINCREMENT. Sonst können kleinere IDs wiederverwendet werden wenn Datensätze gelöscht werden. Das hat aber auch Nachteile/Kosten. Nachzulesen in der SQLite-Dokumentation: https://sqlite.org/autoinc.html
Vielen Dank!
__deets__ hat geschrieben: Dienstag 23. Juli 2019, 10:42 Wenn du mit

Code: Alles auswählen

os.chdir(directory)
connection = sqlite3.connect(database)
ans Ziel kommst, dann kommst du auch mit

Code: Alles auswählen

connection = sqlite3.connect(os.path.join(directory, database))
dahin.
Dankeschön!
NewPython19

Eine weitere Frage :D

Wenn ich mit SELECT die Inhalte eines Datenfelds haben möchte und in eine Liste schreiben möchte (also alle Werte eines Datenfeldes von allen Datensätzen), wie erhalte ich da nur das eine Feld als String und nicht als Tupel?
connection = sqlite3.connect(database)
cursor = connection.cursor()
sql_command = """SELECT Name FROM 'Adress'"""
str(cursor.execute(sql_command))
for name in cursor:
list.append(name)
closeDatabase(connection, cursor) #schließt Verbindung und Cursor
So erhalte ich immer eine Liste mit z. B. [('Meier',), ('Müller',), ('Mustermann',)]
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Du erhältst immer Tuple. Wenn Du die nicht haben willst, entpack sie einfach.

Code: Alles auswählen

names = [name for name, in cursor]
`list` ist ein besonders schlechter Variablenname. Was macht denn `closeDatabase`? Arbeite besser mit with-closing.
NewPython19

"closeDatabase" ist eine Methode von mir, welche die Verbindung zur Datenbank und den Cursor schließt ;)

Danke!
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@NewPython19: Was die Funkion macht ist ja eigentlich schon klar, aber wie schon gesagt ist es besser ``with`` und `contextlib.closing()` zu verwenden. Der Kommentar bei der Zeile wäre auch nicht nötig gewesen.

Ich glaube ich erwähnte schon mal, das man Namen in Python klein_mit_unterstrichen schreibt, also `close_database()` statt `closeDatabase()`.

Es wäre schön wenn Du den Code in die entsprechenden Code-Tags einfasst und nicht als Zitat, denn dabei geht die in Python nicht ganz unwichtige Einrückung in der Anzeige verloren.

Bei Namen in SQL ist Gross-/Kleinschreibung eigentlich egal, aber einige DBMS können da doch Unterschiede machen. Deshalb würde ich Namen dort immer klein schreiben. Dann ist man auch bei einem DBMS-Wechsel auf der sicheren Seite.

Das englische Wort „address“ schreibt sich mit zwei „d“.

Das der Rückgabewert von `cursor.execute()` in eine Zeichenkette umgewandelt wird, mit der dann nicht gemacht wird, macht keinen Sinn.

`list` ist ein sehr schlechter Name für eine Liste, weil man sich damit den Namen des eingebauten Datentyps verdeckt. Grunddatentypen haben in Namen auch nichts verloren.

Das Entpacken eines einzelnen Wertes per ``,`` finde ich persönlich ein bischen zu kryptisch. Das übersieht man leicht.

Ungetestet:

Code: Alles auswählen

import sqlite3
from contextlib import closing

with sqlite3.connect(database) as connection:
    with closing(connection.cursor()) as cursor:
        cursor.execute('SELECT name FROM address')
        names = [row[0] for row in cursor]
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten