python2 mysql select from where and

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
co-se
User
Beiträge: 20
Registriert: Dienstag 20. Oktober 2020, 13:36

Gegeben ist :
CREATE TABLE IF NOT EXISTS `ess` (
`id` int(255) unsigned NOT NULL COMMENT 'ID',
`mid` varchar(255) NOT NULL COMMENT 'MID',
`did` varchar(50) NOT NULL COMMENT 'DID',
`bid` varchar(50) NOT NULL COMMENT 'BID',
`vnname` varchar(150) NOT NULL COMMENT 'Name',
`datum` date NOT NULL COMMENT 'Datum',
`was` varchar(10) NOT NULL COMMENT 'Was',
`rfid` varchar(50) NOT NULL COMMENT 'RFID',
`ort` varchar(50) NOT NULL COMMENT 'Ort',
`jahr` varchar(4) NOT NULL COMMENT 'Jahr',
`zeit1` varchar(8) NOT NULL COMMENT 'Uhrzeit1',
`zeit2` varchar(8) NOT NULL COMMENT 'Uhrzeit2',
`typ` varchar(2) NOT NULL COMMENT 'Typ'
) ENGINE=InnoDB AUTO_INCREMENT=269 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

INSERT INTO `ess` (`mid`, `did`, `bid`, `vnname`, `datum`, `was`, `rfid`, `ort`, `jahr`, `zeit1`, `zeit2`, `typ`) VALUES
('20', 'Santa001', 'Esmeralda001', 'Duck, Don', '2021-04-07', 'Training', '1364111104', 'Cafe', '2021', '09:29:01', ' ', '1');

mal nur eintrag gewählt aus vielen.
Teil1

Code: Alles auswählen

nun = now.strftime('%Y-%m-%d')
card = Reader 
cur = db.cursor()
a= cur.execute("SELECT * FROM hugo WHERE rfid = %s" ,card )
for row in cur.fetchall():
    aff1 = str(row[1])
    aff2 = str(row[2])
    ...
Teil2

Code: Alles auswählen

    cur = db.cursor()
    cur.execute("SELECT * FROM ess WHERE rfid = %s AND datum = %s" ,card ,nun )
    for row in cur.fetchall():
        uff = str(row[0])
        ...

        print (uff)
Teil1 funzt
Teil2 nicht
ich brauche aber eine abfrage bzw die id von einen bestimmten eintrag
weil später unter dieser id die zweite zeit eingetragen wird
die fehlermeldung :
TypeError: execute() takes at most 3 arguments (4 given)
kann ich nichts mit anfangen
Aber wo ist mein fehler ?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Parameter müssen als Liste angegeben werden. Dass Teil1 funktioniert, ist mehr oder weniger Zufall.

Variablennamen sollten aussagekräftig sein. `uff` ist irgendwas lautmalerisches, aber kein guter Name.
Das gilt natürlich auch für Tabellenspalten. mid bid, did? was? häh? Und was soll das vn bei vnname bedeuten?
Zumindest jahr, zeit1 und zeit2 sollten keine Strings sein. Warum hast Du ID als int(255) definiert?
co-se
User
Beiträge: 20
Registriert: Dienstag 20. Oktober 2020, 13:36

Die Variablen haben für mich so Ihre Bedeutung, Spaltennamen Zellennamen sind alle ersetzbar für testzwecke nutze ich solche Namen um einen Überblick zu haben da ich noch viele viele änliche Tabellen habe wo oft sich Namen wiederholen.
Der Aufbau der Tabelle ist schon richtig so,
Über einen Kartenleser wird die RFID von dem CHIP mit einer einer anderen Tabelle verglichen und dort Daten entnommen und in die ess eingetragen.

Ich brauche aber nun eine Abfrage

Code: Alles auswählen

cur.execute("SELECT * FROM ess WHERE rfid = %s AND datum = %s" ,card ,nun )
wo ich eine ID = Primärenschlüssel bekomme wenn beides vorhanden ist
Mit diesem Schlüssel kann ich eine weiter Uhrzeit dazu nach tragen lassen
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@co-se: Die Namen machen halt für fremde keinen Sinn. Und die Erfahrung zeigt das auch *Du* in ein paar Monaten ein Fremder sein wirst. So passieren Fehler die bei ordentlichen Namen nicht passieren würden.

Und es gilt immer noch, dass die Werte als *ein* Argument, nämlich als zweites Argument an `execute()` übergeben werden. Du übergibst da keine zwei Argumente, sondern drei.

Code: Alles auswählen

    cursor.execute(
        "SELECT * FROM ess WHERE rfid = %s AND datum = %s",
        [card_id, ordentlicher_name_fuer_ein_datum],
    )
Statt eines "*" würde man hier die Spaltennamen schreiben. Dann weiss der Leser was da geliefert wird und das ganze ist robuster gegen Änderungen am Tabellenschema.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Auf welchem Planeten ist es denn richtig, daß Jahr ein String ist?
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Die Frage könnte man auch bei Zeiten stellen. Und was für einen Sinn das bei Zeiten macht die Spalte NOT NULL zu deklarieren, dann aber die leere Zeichenkette als Wert für eine Zeit einzutragen. Und wenn Jahr eine Zeichenkette ist, warum dann VARCHAR(4) und nicht CHAR(4). Da sind wahrscheinlich auch noch ein paar andere Kandidaten für CHAR statt VARCHAR.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
co-se
User
Beiträge: 20
Registriert: Dienstag 20. Oktober 2020, 13:36

Jahr = String hängt damit zusammen das ich alle einträge für jedes Jahr sofort abrufen kann was ich für anderer zwecke schon so nutze allerdings alles unter php wegen Webseite.
* = habe ich gewählt da ich nocht nicht weis ob ich weitere Felder benötige wenn ich statt den * eine Zelle abfrage kann ich fetchone nutzen
mir ist erstmal wichtig das es läuft was ich da brauche

dieser aufbau läuft auf eigene hardware unabhängig vom eigendlichen system
aus diesem grund auch sind meine names vergabe für viele nicht logisch muß auch nicht weil es nur testaufbau ist
co-se
User
Beiträge: 20
Registriert: Dienstag 20. Oktober 2020, 13:36

Danke es passt
habe den fehler gefunden
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Was hat denn die Abfrage damit zu tun, dass Du einen String statt einer Zahl benutzt?
Und ist es so, dass das jahr aus datum identisch ist? Dann ist das unsinnige doppelte Datenhaltung, weil man mit SQL auch nur das Jahr eines date-Feldes abfragen kann.
co-se
User
Beiträge: 20
Registriert: Dienstag 20. Oktober 2020, 13:36

das das jahr im datum schon drin ist ist mir klar aber ich wollte weniger code und schnellere abfrage damit erziehlen
mir ist bekannt das ich das datum in SQl rein bekommen JJJJ-MM-TT
ich habe programme wo ich so ein datum wwie oben (JJJJ-MM-TT) und einzell also ( JJJJ ) und ( MM ) und ( TT ) speichere
mit list unter PHP kann ich immer das Datum zerlegen aber wie oben gesagt für schneller abfrage und weniger code
wenn ich richtig weiß sind string nichts anderes als variable zeichenketten
da die rfid nicht immer die selbe ist
ich teste mein programm mit 2 Chips oder karten aber im vollen einsatz sind rund 200 chips oder karten im einsatz
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@co-se: Datenbanken können mit den native DateTime-Formaten recht gut umgehen. Hast Du mal ein Profiling vorgenommen um Deine Annahme, dass es mit Strings schneller geht, zu stützen? Ansonsten sehe ich hier die Gefahr des premature optimizations (das womöglich gar keinen maßgebliche Optimierung bringt) in Verbindung mit ungünstig gewählten Datentypen, sowie schlecht gewählten Variablennamen. Das wären direkt drei Schritte auf einmal in Richtung einer beschwerlichen Zukunft der Programmpflege.
co-se
User
Beiträge: 20
Registriert: Dienstag 20. Oktober 2020, 13:36

habe unterlagen erst gefunden zum MCDBA aber noch nie rein geschaut
aus zeit mangel
derzeit will ich erstmal das wo ich am laufen habe beenden
das mit python steht zu 50% es fehlt nur noch der richtige start,
nach der aufgabe sind 2 weitere noch offen allerdings mit einen Arduinowo ich schon mit 1 von den 2 angefangen habe
wenn all das fertig ist werde ich mich mal weiter mit DB beschäftigen
zwischen den ganzen sachen habe ich noch Stromleitungen im kopf welche zum Teil neu verlegt und einige nur umgelegt werden müßen
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@co-se: Falls das „wenn ich richtig weiß sind string nichts anderes als variable zeichenketten“ sich auf VARCHAR bezog: Nicht alle Deine Zeichenketten sind ”variabel”, denn das var(iable) in VARCHAR bezieht sich auf die Länge der Zeichenkette. Vierstellige Jahreszahlen sind aber beispielsweise gar nicht variabel in der Länge und selbst wenn bei etwas wie `typ` VARCHAR(2) auch einstellige Typen vorkommen können, würde man da in der Regel CHAR(2) nehmen. VARCHAR belegt variablen Speicherplatz und ist für die Datenbank komplizierter zu speichern und zu verarbeiten. Wenn man schon aus fragwürdigen Optimierungsgründen Strings für redundante Jahresangaben nutzt, sollten die nicht auch noch VARCHAR sein. Wobei ich da beispielsweisweise auch nicht verstehe warum die nicht einfach INT oder UNSIGNED TINYINT sind, wenn Du schon ”optimieren” willst.

Letztlich ist es aber effizienter und weniger fehleranfällig die Jahreszahl einfach aus einem TIMESTAMP zu holen. Wie schon geschrieben wurde: Datenbanken sind gut darin das zu machen. Das ist eine wirklich häufig verwendete Operation, und die wird interrn auf Zahlen ausgeführt, nicht auf Zeichenketten, was letztlich komplizierter und langsamer sein wird.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten