MSSQL - Bestimmtes Datum auslesen

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Juliusvanvern
User
Beiträge: 15
Registriert: Mittwoch 22. Januar 2020, 20:53

Hallo zusammen.

Ich möchte gerne von einer "winzigen" MS-SQL-DB nur die Werte auslesen, die ein bestimmtes Datum haben.

Ich habe mit pyodbc eine Verbindung zu der Datenbank hergestellt und dachte mir ich nutze pandas zur Datenanalyse (pd)

Im MS-SQL-Server Management Studio habe ich eine Query getestet um alle Zeilen anzuzeigen welche ein bestimmtes Datum haben. Das funktioniert auch:

Code: Alles auswählen

SELECT * FROM kunden.dbo.kunden_kundennamen 
WHERE EndDate = '2021-10-18'
Ganz unbedarft bin ich nun heran gegangen und habe versucht dies in Python zu bewerkstelligen. Aber es klappt leider nicht.

Fehler: "SyntaxError: invalid syntax. Perhaps you forgot a comma?" an einem bestimmten Punkt habe ich wohl was vergessen.

Code: Alles auswählen

from typing import ValuesView
import pyodbc
import pandas as pd
import sqlalchemy as sa

cnxn = pyodbc.connect("Driver={ODBC Driver 17 for SQL Server};"
                      "Server=DESKTOP-UP2PHSF\SQLEXPRESS;"
                      "Database=kunden;"
                      "Trusted_Connection=yes;")

EndDate = pd.read_sql_query('SELECT * FROM kunden.dbo.kunden_kundennamen WHERE EndDate = '2021-10-18'', cnxn)
print(EndDate)
Wenn ich mit folgender Query testweise alles auslesen möchte, funktioniert es.

Code: Alles auswählen

data = pd.read_sql_query('SELECT * FROM kunden.dbo.kunden_kundennamen', cnxn)
print(data)
Kann es sein, das ich ggf. das Datum konvertieren muss? Vielleicht erwartet er ja ein String und ich versuche aber ein Datumsformat auszulesen.

PS: EndDate hat den Datentyp Date in MSSQL

Könnt ihr mir auf die Sprünge helfen? Das währe sehr nett. Vielen Dank
Zuletzt geändert von Juliusvanvern am Donnerstag 17. Februar 2022, 20:34, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Strings müssen in Anführungszeichen gesetzt werden. Jetzt schau mal, wo Deine Strings anfangen und wo sie aufhören. Das kann man schon gut an der Farbe erkennen.
Juliusvanvern
User
Beiträge: 15
Registriert: Mittwoch 22. Januar 2020, 20:53

Sirius3 hat geschrieben: Donnerstag 17. Februar 2022, 20:23 Strings müssen in Anführungszeichen gesetzt werden. Jetzt schau mal, wo Deine Strings anfangen und wo sie aufhören. Das kann man schon gut an der Farbe erkennen.
Ich habe es nun so gemacht, da später die Eingabe im Deutschen Datumsformat getätigt werden soll.

Code: Alles auswählen

EndDate = pd.read_sql_query('SELECT * FROM kunden.dbo.kunden_kundennamen WHERE EndDate = CONVERT(DATETIME, '"18-10-2021"', 104)', cnxn)
print(EndDate)
Zumindest bekomme ich keinen Fehler mehr, aber meine Abfrage bleibt leer.

Meine Query in der Datenbank direkt, funktioniert und liefert mir alle drei Werte mit dem Datum.

Code: Alles auswählen

SELECT * FROM kunden.dbo.kunden_kundennamen 
WHERE EndDate = CONVERT(datetime, '18-10-2021', 104)
Kann es sein, das ich mit der Angabe nach einem String suche, er aber eigentlich ein Format vom Typ Date erwartet?
Benutzeravatar
sparrow
User
Beiträge: 4183
Registriert: Freitag 17. April 2009, 10:28

Die Antwort von Sirius3 bleibt korrekt.
Zeig doch mal, wo die Zeichenkette, die die SQL-Query enthält, beginnt und wo sie aufhört.
Juliusvanvern
User
Beiträge: 15
Registriert: Mittwoch 22. Januar 2020, 20:53

sparrow hat geschrieben: Donnerstag 17. Februar 2022, 20:56 Die Antwort von Sirius3 bleibt korrekt.
Zeig doch mal, wo die Zeichenkette, die die SQL-Query enthält, beginnt und wo sie aufhört.
:P Nicht sicher was du jetzt genau meinst, aber ich versuche es zu beantworten.

Meine Query ist ja das

Code: Alles auswählen

SELECT * FROM kunden.dbo.kunden_kundennamen WHERE EndDate = CONVERT(DATETIME, '"18-10-2021"', 104)
Den auszulesenden Wert habe ich nun in doppelte Hochkomma gesetzt. Damit die Query generell funktioniert muss ich sie in ' ' einpacken.
Benutzeravatar
sparrow
User
Beiträge: 4183
Registriert: Freitag 17. April 2009, 10:28

Also, wenn du der Parser bist, und du siehst diese Zeichenkettendefinition:

Code: Alles auswählen

'SELECT * FROM kunden.dbo.kunden_kundennamen WHERE EndDate = CONVERT(DATETIME, '"18-10-2021"', 104)'
Dann guckst du dir die vorne and und weißt: Sehr gut eine Zeichenkette, die mit einem einfachen Hockomma beginnt. Ich weiß, dass die bei dem nächsten nicht maskierten einfachem Hochkomma endet.
Das nächste nicht masierte Hochkomma ist nicht nach der schließenden Klammer. Das sieht man - wie hier bereits angemerkt - auch an der Einfärbung durch das Syntax Highlighting.

Da man in Python mindestens 4 Arten hat um Zeichenketten zu kennzeichnen, würde ich vorschalgen, du nimmst nocht ausgerechnet ein einfaches Hochkomma, dass du offensichtlich in der Zeichenkette selbst noch verwenden willst.
Juliusvanvern
User
Beiträge: 15
Registriert: Mittwoch 22. Januar 2020, 20:53

Ich hab es nun so.

Code: Alles auswählen

EndDate = pd.read_sql_query('SELECT EndDate FROM kunden.dbo.kunden_kundennamen WHERE EndDate = CONVERT(DATETIME, ''18-10-2021'', 104)', cnxn) # Funktioniert, aber Data Frame ist leer
print(EndDate)
Jedoch bleibt der Ausgabe wert leer.

Wenn ich es so versuche

Code: Alles auswählen

ndDate = pd.read_sql_query('SELECT * FROM kunden.dbo.kunden_kundennamen WHERE EndDate = ''2021-10-18''', cnxn) # Hier kommt date is incompatible with int 
print(EndDate)
gibt er mir ein Int zurück was ja in dem Fall nicht mit dem Type Date zusammen passt.

Ich hab das Gefühl, ich laufe die ganze Zeit um den Fehler drum herum, aber sehe ihn nicht. :lol: Irgendwann bekomme ich das bestimmt noch hin.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Schau Dir doch einfach mal an, was Du hier für literale Strings erzeugst.
'abc''123' ist das selbe wie 'abc123' weil einfach zwei Strings zusammengesetzt werden.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Code: Alles auswählen

>>> s = 'abc''123'
>>> s
'abc123'
>>> s = 'abc'                   '123'
>>> s
'abc123'
>>> s = 'abc'"123"'def'
>>> s
'abc123def'
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
__blackjack__
User
Beiträge: 13064
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Das mit `pyodbc` so zu verwenden kann vielleicht funktionieren, muss es aber nicht, denn die Dokumentation von Pandas garantiert das ausschliesslich für das `sqlite3`-Modul. Wenn man andere DBs verwenden will, erwartet Pandas, das man über SQLAlchemy geht. Die Dokumentation zu dem Argument ist da sehr deutlich:
con : SQLAlchemy connectable, str, or sqlite3 connection
Using SQLAlchemy makes it possible to use any DB supported by that
library. If a DBAPI2 object, only sqlite3 is supported.
`cnxn` ist übrigens kein wirklich guter Name.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Juliusvanvern
User
Beiträge: 15
Registriert: Mittwoch 22. Januar 2020, 20:53

__blackjack__ hat geschrieben: Freitag 18. Februar 2022, 03:13 Das mit `pyodbc` so zu verwenden kann vielleicht funktionieren, muss es aber nicht, denn die Dokumentation von Pandas garantiert das ausschließlich für das `sqlite3`-Modul. Wenn man andere DBs verwenden will, erwartet Pandas, das man über SQLAlchemy geht. Die Dokumentation zu dem Argument ist da sehr deutlich:
con : SQLAlchemy connectable, str, or sqlite3 connection
Using SQLAlchemy makes it possible to use any DB supported by that
library. If a DBAPI2 object, only sqlite3 is supported.
`cnxn` ist übrigens kein wirklich guter Name.
Ahh okay. Vielen Dank. Dann werde ich mir mal die Dokumentation von SQLAlchemy zu Gemüte führen. :D
Juliusvanvern
User
Beiträge: 15
Registriert: Mittwoch 22. Januar 2020, 20:53

Sirius3 hat geschrieben: Donnerstag 17. Februar 2022, 22:43 Schau Dir doch einfach mal an, was Du hier für literale Strings erzeugst.
'abc''123' ist das selbe wie 'abc123' weil einfach zwei Strings zusammengesetzt werden.
Danke dir Sirius, das hab ich gar nicht so gesehen.

Ich habe es nun versucht so umzusetzen.

Verbindung erstelle ich mit SQLAlchemy her. Das funktioniert gut, gibt mir auch die Werte wieder die ich erwarte wenn ich das Datum explizit in der Query angeben.

Nun habe ich damit rumgespielt, eine kleine Eingabeaufforderung zu erstellen, das Datum wird in der Deutschen Form angegeben und in das Format umgewandelt wie es in der Tabelle zu finden ist. Ich verstehe noch nicht so recht, wie ich mit der Variable, die ja nun einen String enthält, in meiner Query weiter machen kann. Lässt sich der String denn noch einmal in ein Datumsformat umwandelt?

Code: Alles auswählen

import sqlalchemy as sa
from sqlalchemy import create_engine
from sqlalchemy import text
from datetime import datetime

from sqlalchemy.sql.sqltypes import DATETIME

SERVER = 'DESKTOP-UP2PHSF\SQLEXPRESS'
DATABASE = 'kunden' 
DRIVER = 'ODBC Driver 17 for SQL Server'
USERNAME = '' 
PASSWORD = ''
DATABASE_CONNECTION = f'mssql://{USERNAME}:{PASSWORD}@{SERVER}/{DATABASE}?driver={DRIVER}'

engine = create_engine(DATABASE_CONNECTION)
connection = engine.connect()

usrEnter = input("Datum angeben: ")
date = datetime.strptime(usrEnter, '%d.%m.%Y')
usrEndDate = date.strftime('%Y-%m-%d')
print(type(usrEndDate))
print(usrEndDate)


datetest = '18-10-2021'
datetestdate = 2021-10-18


print(type(usrEndDate)) #string
print(type(datetest)) #string
print(type(datetestdate)) #int
print(type(date)) #datetime



with engine.connect() as conn:
    EndDate = conn.execute("SELECT * FROM kunden.dbo.kunden_kundennamen WHERE EndDate = CONVERT(datetime, '18-10-2021', 104)")
    for row in EndDate:
        Name = row.kdname
        KdNr = row.kdnr
        EndDatum = row.EndDate
        #print(f"Name: {row.kdname}  KdNr: {row.kdnr} End Datum: {row.EndDate}")
        print(KdNr, Name, EndDatum)
Meine Ausgabe die ich erhalte:

Code: Alles auswählen

Datum angeben: <class 'str'>
2021-10-18
<class 'str'>
<class 'str'>
<class 'int'>
<class 'datetime.datetime'>
2 Müller 2021-10-18
3 Busch 2021-10-18
Der Thread 'MainThread' (0x1) hat mit Code 0 (0x0) geendet.
Das Programm "python.exe" wurde mit Code 0 (0x0) beendet.
Ich danke euch schon für eure letzten Denkanstöße. :)
Juliusvanvern
User
Beiträge: 15
Registriert: Mittwoch 22. Januar 2020, 20:53

Ich glaube nun hab ich es..

Code: Alles auswählen

("SELECT * FROM kunden.dbo.kunden_kundennamen WHERE EndDate =?", usrEndDate)
Ich habe die Variable immer versucht direkt in die Query mit aufzunehmen. Das hat nicht funktioniert. So geht es jedoch scheinbar.
Antworten