Datum in SQL-Abfrage

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Musiker123
User
Beiträge: 26
Registriert: Donnerstag 7. März 2019, 09:48

Donnerstag 15. Oktober 2020, 14:20

Hallo zusammen,

folgendes funktioniert:

cursor.execute ("select Feld1, Feld2.... FROM Table1 where Belegdatum >= '2020-07-01' ...usw

wenn ich nun das Datum durch eine Platzhalter ersetzen will z.B. VON = '2020-07-01'

cursor.execute ("select Feld1, Feld2.... FROM Table1 where Belegdatum >= {} ....".format (VON))

funktioniert es nicht mehr. Er bringt mir alle Datensätze der Datenbank.

Das Feld Belegdatum hat den Type=Datetime

Ich habe auch schon das Feld "VON" in ein Datetime-Feld umgewandelt ( VON = datetime.date (2020,7,1) oder VON = datetime.datetime(2020,7,1)).
Funktioniert auch nicht!

Im Feld Belegdatum steht '2020-07-23 00:00:00')

Also, es tauchen keine Fehlermeldungen auf, er selektiert einfach nicht ab dem gewünschten Datum wenn ich über Platzhalter arbeite.

Hat jemand eine Idee?

Vielen Dank vorab.
Sirius3
User
Beiträge: 13054
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 15. Oktober 2020, 14:36

Formatiere niemals Werte in ein SQL-Statement. Benutze Platzhalter. Die können von DB-Anbindung zu DB-Anbindung verschieden sein, das mußt Du in der Dokumentation nachlesen.
Hier für SQLite:

Code: Alles auswählen

von = datetime.date (2020,7,1)
cursor.execute("select Feld1, Feld2.... FROM Table1 where Belegdatum >= ?", [von])
Musiker123
User
Beiträge: 26
Registriert: Donnerstag 7. März 2019, 09:48

Donnerstag 15. Oktober 2020, 15:31

Hab das jetzt wie folgt gelöst:

Data = ('2020-10-01',)

sql_query = """SELECT Tab1, Buchungsnr, KontoSoll, ....... Kost2Betrag \
FROM {}.sg_fib_buch WHERE substr(Belegdatum,1,10) > %s and Kost2 <> ' ' ORDER BY Kost2 """.format(mand)

cursor.execute(sql_query, Data)

Er löst die {} und %s ja nun nacheinander auf!

Vielen Dank
Sirius3
User
Beiträge: 13054
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 15. Oktober 2020, 15:52

Bei Data solltest Du datetime verwenden und nicht irgendwelche String-Operationen. Das ist ja in der Datenbank hoffentlich auch ein TIMESTAMP-Feld.
Tabellennamen sollten nicht Variabel sein.
Das \ kann und sollte weg.
Musiker123
User
Beiträge: 26
Registriert: Donnerstag 7. März 2019, 09:48

Donnerstag 15. Oktober 2020, 17:37

Ich lerne gern dazu:

warum keinen variablen DB-Name?
Ich habe eine DB mit 15 Mandanten (mandxx) mit darunter liegenden Tabellen.
Soll ich dann 15 if-Abfragen mit 15 SELECTS starten?
Die Datenmenge in den Tabellen ist überschaubar, somit sollte das die Antwortzeiten
keinen Einfluss haben.
Zudem der Tabellenname ja schon über den Format-Befehl vorher aufgelöst wird!

Das Datumsfeld ist ein Belegdatum, also kein Timestamp, aber das kann ich ja gleich
gern einmal mit datetime ausprobieren.

Ich habe hier übrigens eine MySQL-DB.

Vielen Dank für die Anregungen!
Benutzeravatar
__blackjack__
User
Beiträge: 7056
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Donnerstag 15. Oktober 2020, 17:43

@Musiker123: Weil Datenbank und Tabellennamen nicht variabel sind. Das ist so von SQL nicht vorgesehen, das macht man nicht. Die Mandanten sind Daten und die gehören *in* die Tabellen, nicht in die Strukturbeschreibung der Datenbank(en). Da braucht man dann nicht 15 ``if``\s sondern eine weitere Bedingung im WHERE, die auf den Mandanten einschränkt. Womit dann auch das Anlegen und Löschen von Mandanten plötzlich viel einfacher wird, und sich eine Liste über alle Mandanten zu erstellen, oder die Datensicherung, oder…
long long ago; /* in a galaxy far far away */
Musiker123
User
Beiträge: 26
Registriert: Donnerstag 7. März 2019, 09:48

Samstag 17. Oktober 2020, 09:16

Ich will immer noch lernen!

vielleicht irre ich mich auch, aber ich habe auf dem Datenbankmanagementsystem, dem MySQL-Server, mehrere Datenbanken zur Verfügung.

Ich melde mich hier mit "mysql.connector.connect" an und gehe dabei auf eine IP-Adresse (host=xxx.xxx.xxx.xxx), gebe aber hier noch keine Datenbank (db) an,
sondern löse es in dem SELECT.

Für jede Datenbank gibt es nun einen Ordner. Jeder Ordner repräsentiert einen Mandanten.

Um jetzt auf eine Datenbank zuzugreifen muss ich die gewünschte Tabelle über (Mandant.Tablename) ansprechen.
Beispiel: mand99.sg_fib_buch. mand99 ist hier die Datenbank.
In jedem Ordner (Mandanten) befinden sind die gleichen Tabellen..
Sag mir bitte, wie ich das mit einem SELECT/Where lösen kann!
Um nun mein Programm für alle Datenbanken/Mandanten nutzen zu können, sehe ich keine andere Möglichkeit als über Variablen zu arbeiten.
Bei dem DBMS-System handelt es sich um einen großen Hersteller von ERP-Software.
Also, auf das Design der DB habe ich leider keinen Einfluss.
Wenn Du eine bessere/andere IDEE hast, würde ich mich freuen!
Vielen Dank und ein schönes WE
Benutzeravatar
__blackjack__
User
Beiträge: 7056
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Samstag 17. Oktober 2020, 09:27

@Musiker123: Die Einschränkung, dass Du auf den DB-Entwurf keinen Einfluss hast ist neu. Wenn die ERP-Software nicht mehrmandantenfähig ist, dann kann man da natürlich nichts machen.
long long ago; /* in a galaxy far far away */
__deets__
User
Beiträge: 8638
Registriert: Mittwoch 14. Oktober 2015, 14:29

Samstag 17. Oktober 2020, 09:31

Komischer Entwurf von Seiten des Herstellers. Wenn es dabei um Zugriffsschutz geht, würde ich das anders lösen.

Wie dem auch sei - wenn das dein Problem ist, dann würde ich einfach pro Mandant eine Verbindung machen. Dadurch wird die Auswahl des Mandanten zentral an einer Stelle getätigt, und der ganze Code später muss sich damit nicht auseinandersetzen.
Antworten