Seite 3 von 4
Verfasst: Freitag 28. April 2006, 07:53
von jens
stigi hat geschrieben:und mein fehler lag daran, dass ich nicht gewusst hab wie ich den python string in meine sql abfrage einbaue, was ich jetzt so gelöst hab:
Code: Alles auswählen
cur.execute("UPDATE REGEL20 SET PA_INFO = '" + string2 + "' WHERE '" + string1 + "' <> '" + string2 + "'")
Wie schon mal erwähnt sollte man die SQL Escaping Funktion des Datenbank Moduls in jedem Fall nutzten!
siehe auch:
[wiki]Thema Sicherheit#Tipps[/wiki]
[wiki]Parametrisierte SQL Queries[/wiki]
Verfasst: Freitag 28. April 2006, 07:55
von stigi
alles klar danke

mitlerweile hab ich zwar schonwieder das nächste problem

aber ich versuchs erstmal selbst

Verfasst: Freitag 28. April 2006, 13:04
von stigi
ok, da ich mal wieder nich vorran komm, meine nächste frage
hier nochmal kurz die rahmengeschichte dazu:
ich muss mit python eine access datenbank auf fehler untersuchen und diese fehler korrigieren. durchsucht wird die tabelle regel20 in der spalte PA_INFO. in der tabelle regel20 in der spalte PA_INFO_TEXTNR steht eine referenznummer hinter der sich in tabelle TEXTE der originaltext verbirgt. es soll also abgeglichen werden ob der text in regel20.pa_info mit dem original in texte.tex_ausgabe übereinstimmt.
hier der code den ich bisher habe:
Code: Alles auswählen
import dbi
import odbc
conn = odbc.odbc('DRIVER=Microsoft Access-Treiber (*.mdb);UID=admin;DBQ=C:\\temp\\T100_V46.mdb')
cur = conn.cursor()
sql = "SELECT DISTINCT PA_INFO, PA_INFO_TEXTNR, TEX_AUSGABE FROM Regel20, TEXTE WHERE REGEL20.PA_INFO_TEXTNR = TEXTE.TEX_NUMMER and TEXTE.TEX_SPRACHE ='deu' and REGEL20.PA_INFO <> TEXTE.TEX_AUSGABE" #where PA_INFO like '%Runden%'
cur.execute(sql)
rows = cur.fetchall()
cur.close()
conn.close()
for row in rows:
# row[0], fuer das erste Element in der SQL anweisung, row[1] fuer das zweite usw...
string1 = row[0]
string2 = row[2]
print string1
print row[1]
print string2
print
conn = odbc.odbc('DRIVER=Microsoft Access-Treiber (*.mdb);UID=admin;DBQ=C:\\temp\\T100_V46.mdb')
cur = conn.cursor()
cur.execute("UPDATE REGEL20 SET PA_INFO = '" + string2 + "' WHERE '" + string1 + "' <> '" + string2 + "' and REGEL20.PA_INFO_TEXTNR = TEXTE.TEX_NUMMER and TEXTE.TEX_SPRACHE='deu'")
cur.close()
conn.close()
wenn in der tabelle regel20 jetzt alles korrekt ist läuft das script und bringt keine fehler. wenn ich jetzt aber einen wert verändere, und dieser dann automatisch korrigiert werden soll, was ja sinn und zweck der übung ist, kommt dieser fehler:
Code: Alles auswählen
Traceback (most recent call last):
File "Y:\....\spe4.py", line 23, in ?
cur.execute("UPDATE REGEL20 SET PA_INFO = '" + string2 + "' WHERE '" + strin
g1 + "' <> '" + string2 + "' and REGEL20.PA_INFO_TEXTNR = TEXTE.TEX_NUMMER and T
EXTE.TEX_SPRACHE='deu'")
dbi.program-error: [Microsoft][ODBC Microsoft Access Driver] 2 Parameter wurden
erwartet, aber es wurden zu wenig Parameter ³bergeben. in EXEC
ich weis, das etwas an meiner 2. SQL Abfrage mit dem Update was nicht stimmt, ich komm aber nicht drauf

Verfasst: Freitag 28. April 2006, 13:25
von N317V
Bau doch den Query-String erstmal nicht innerhalb des execute-Aufrufs zusammen und lass Dir nur mal den ausgeben. Erstens könntest Du so schneller sehen, wenn da ein Tippfehler drin ist (sieht nicht so aus, hab das grad getestet) und dann kannst Du Dir diesen String mal kopieren und direkt in Access testen. Möglicherweise bekommst Du dann eine aussagekräftigere Fehlermeldung als über ODBC. Am besten Du packst das ganze in eine try...except-Konstruktion und lässt Dir den Query-String im except-Fall ausgeben. (Toll formulieren tu ich heut auch wieder

) So in der Art:
Code: Alles auswählen
qry = "UPDATE REGEL20 SET PA_INFO = '" + string2 + "' WHERE '" + string1 + "' <> '" + string2 + "' and REGEL20.PA_INFO_TEXTNR = TEXTE.TEX_NUMMER and TEXTE.TEX_SPRACHE='deu'"
try:
cur.execute(qry)
except:
print qry
So bekommst Du genau die Query, die fehlschlägt.
Verfasst: Dienstag 2. Mai 2006, 06:46
von stigi
sodele, das hab ich mal gemacht, habe mein script noch etwas umgebaut zwecks wartung und einfacher lesbarkeit
Code: Alles auswählen
import dbi
import odbc
conn = odbc.odbc('DRIVER=Microsoft Access-Treiber (*.mdb);UID=admin;DBQ=C:\\temp\\T100_V46.mdb')
curForSelect = conn.cursor()
curForUpdate = conn.cursor()
sql = "SELECT DISTINCT PA_INFO, PA_INFO_TEXTNR, TEX_AUSGABE FROM Regel20, TEXTE WHERE REGEL20.PA_INFO_TEXTNR = TEXTE.TEX_NUMMER and TEXTE.TEX_SPRACHE ='deu' and REGEL20.PA_INFO <> TEXTE.TEX_AUSGABE" #where PA_INFO like '%Runden%'
curForSelect.execute(sql)
rows = curForSelect.fetchall()
for row in rows:
# row[0], fuer das erste Element in der SQL anweisung, row[1] fuer das zweite usw...
string1 = row[0]
string2 = row[2]
print string1
print row[1]
print string2
print
sql2 = ("UPDATE REGEL20 SET PA_INFO = '%s' WHERE REGEL20.PA_INFO <> TEXTE.TEX_AUSGABE and REGEL20.PA_INFO_TEXTNR = TEXTE.TEX_NUMMER and TEXTE.TEX_SPRACHE='deu'" % (string2))
#curForUpdate.execute(sql2)
try:
curForUpdate.execute(sql2)
except:
print sql2
curForSelect.close()
curForUpdate.close()
conn.close()
folgende Ausgabe bekomm ich jetzt:
Code: Alles auswählen
Y:\Mitarbeiter\...\pythonwin>spe6
Runddden
63308
Runden
UPDATE REGEL20 SET PA_INFO = 'Runden' WHERE REGEL20.PA_INFO <> TEXTE.TEX_AUSGABE
and REGEL20.PA_INFO_TEXTNR = TEXTE.TEX_NUMMER and TEXTE.TEX_SPRACHE='deu'
Die erste Zeile mit Runddden ist der Fehler in meiner Tabelle der Korrigiert werden soll, also findet er ihn zumindest schonmal.
Die zweite Zeile ist die dazugehörige Referenznummer, die stimmt auch und in der 3. Zeile steht auch schon das original welches über das falsche drübergeschrieben werden soll.
darunter die SQL Query die leider so nich funktioniert

Verfasst: Dienstag 2. Mai 2006, 07:09
von gerold
stigi hat geschrieben:Code: Alles auswählen
UPDATE REGEL20 SET PA_INFO = 'Runden' WHERE REGEL20.PA_INFO <> TEXTE.TEX_AUSGABE
and REGEL20.PA_INFO_TEXTNR = TEXTE.TEX_NUMMER and TEXTE.TEX_SPRACHE='deu'
Hi stigi!
Wenn du diese SQL-Anweisung in eine Access-Abfrage kopierst und dann ausführst -- was sagt Access dann dazu?
mfg
Gerold

Verfasst: Dienstag 2. Mai 2006, 07:26
von stigi
kann ich die abfrage in access irgendwo 1:1 hinkopieren oder muss ich mir das über den assistenten oder die entwurfsansicht zusammen stückeln ?
edit: schon gefunden

ich poste gleich das ergebnis
Verfasst: Dienstag 2. Mai 2006, 07:31
von gerold
stigi hat geschrieben:kann ich die abfrage in access irgendwo 1:1 hinkopieren oder muss ich mir das über den assistenten oder die entwurfsansicht zusammen stückeln ?
Hi stigi!
Neue Abfrage in der Entwurfsansicht --> Fenster "Tabelle anzeigen" schließen ohne neue Tabelle hinzuzufügen --> Menü: Ansicht --> SQL-Ansicht.
Menü: Abfrage --> Ausführen.
mfg
Gerold

Verfasst: Dienstag 2. Mai 2006, 07:36
von stigi
also im access funktioniert das query ohne Probleme. Access frägt mich nach 3 Werten:
nach TEXTE.TEX_AUSGABE - da geb ich dann das original ein 'Runden'
nach TEXTE.TEX_NUMMER - da geb ich die referenznummer 63308 ein
und nach TEXTE.TEX_SPRACHE - da geb ich dann 'deu' ein
damit wird genau dieses eine Feld welches ich korrigieren möchte korrekt verändert.
was nun? dann is was an meinem script falsch oder?
ahja danke für die access hilfe, hatte es grad selbst gefunden
hier die ausgabe wenn ich es im script ausführe:
Code: Alles auswählen
Y:\Mitarbeiter\heilemannpa\pythonwin>spe6
Runddden
63308
Runden
Traceback (most recent call last):
File "Y:\Mitarbeiter\...\pythonwin\spe6.py", line 20, in ?
curForUpdate.execute(sql2)
dbi.program-error: [Microsoft][ODBC Microsoft Access Driver] 3 Parameter wurden
erwartet, aber es wurden zu wenig Parameter ³bergeben. in EXEC
Verfasst: Dienstag 2. Mai 2006, 08:13
von gerold
stigi hat geschrieben:also im access funktioniert das query ohne Probleme. Access frägt mich nach 3 Werten:
nach TEXTE.TEX_AUSGABE - da geb ich dann das original ein 'Runden'
nach TEXTE.TEX_NUMMER - da geb ich die referenznummer 63308 ein
und nach TEXTE.TEX_SPRACHE - da geb ich dann 'deu' ein
Hi stigi!
Da haben wir ja schon das Problem. Access fragt dich immer nur dann nach Parametern, wenn es einen Ausdruck nicht kennt. "TEXTE.TEX_AUSGABE" ist so ein Ausdruck. Woher soll Access denn wissen, dass du damit ein Tabellenfeld meinst? Du hast in der SQL-Anweisung ja kein "FROM" mit drinnen, das dem Access mitteilen würde, welche Tabellen erwartet werden. Ob dieses Feature (mit mehreren Tabellen) von Access überhaupt unterstützt wird, dass weiß ich auch nicht. Das müsste man ausprobieren oder nachschlagen.
Aber um die ganze Sache nicht zu kompliziert werden zu lassen --> hier die einfache Lösung:
Finde in der ersten SQL-Anweisung alle notwenigen Werte heraus und verwende die Werte, nicht die Felder, in der zweiten SQL-Anweisung.
So auf diese Art:
Code: Alles auswählen
sql = """
SELECT
id, vorname, nachname
FROM
adressen
WHERE
(id = 1)
"""
cur.execute(sql)
id, vorname, nachname = cur.fetchone()
sql = """
UPDATE andere_tabelle
SET
vorname = '%(vorname)s',
nachname = '%(nachname)s'
WHERE
(id = %(id)s)
""" % {
"id": id,
"vorname": vorname,
"nachname": nachname
}
cur.execute(sql)
Dieser Code soll nur verdeutlichen, wie ich das meine.
mfg
Gerold

Verfasst: Dienstag 2. Mai 2006, 09:16
von stigi
jippi funktioniert
habs durch klammersetzung hinbekommen ihm zu sagen, dass es sich um ein Tabellenfeld handelt

und wenn ich ihm beim UPDATE beiden Tabellen mitgeb, weis er auch was zu tun ist
Code: Alles auswählen
sql2 = ("UPDATE REGEL20, TEXTE SET REGEL20.PA_INFO = '%s'WHERE ((REGEL20.PA_INFO<>TEXTE.TEX_AUSGABE And REGEL20.PA_INFO_TEXTNR=TEXTE.TEX_NUMMER And TEXTE.TEX_SPRACHE='deu'));" %(string3))
curForUpdate.execute(sql2)
jetzt kann ich weiterarbeiten

Verfasst: Freitag 5. Mai 2006, 06:45
von stigi
sodele, jetzt hab ich auch schon das nächste Problem. Und zwar:
Ist es im SQL möglich die Abfragen case-sensitive zu gestalten? also wenn ich zwei felder mit dem Inhalt "Runden" und "runden" vergleich, sollen die als ungleich gelten, bisher sagt SQL leider, dass sie identisch sind.
edit:schon hinbekommen

edit2:das geht leider nur für den ersten Buchstaben des strings, muss aber für alle gehen, brauche also doch hilfe

Datenbankzugriff Python => Access 2007
Verfasst: Freitag 28. September 2007, 10:46
von Aquerias
Hallo,
ich bin neu hier und habe ein Problem.
Genau wie Stigi möchte ich mit Python auf eine Access (2007) Datenbank zugreifen. Allerdings habe ich schon einige Vorschläge ausprobiert und meinen Fehler noch nicht gefunden.
Mein Python Code bisher:
>>> import dbi
>>> import odbc
>>> try:
... s = odbc.odbc('DRIVER=(Microsoft Access Driver (*.accdb));UID=admin;DBQ=C:\\Test.accdb')
Die Fehlermeldung:
Traceback (most recent call last):
File "<interactive input>", line 2, in ?
dbi.operation-error: [Microsoft][ODBC Driver Manager] Der Datenquellenname wurde nicht gefunden, und es wurde kein Standardtreiber angegeben in LOGIN
Es scheint so, dass ich irgendetwas vergessen habe.
Muss ich unter START\Systemsteuerung\Verwaltung\Datenquellen (ODBC)
noch etwas konfigurieren?
Gruß und schon mal Danke
Aquerias
Re: Datenbankzugriff Python => Access 2007
Verfasst: Freitag 28. September 2007, 11:14
von gerold
Aquerias hat geschrieben:s = odbc.odbc('DRIVER=(Microsoft Access Driver (*.accdb));UID=admin;DBQ=C:\\Test.accdb')
Hallo Aquerias!
Willkommen im Python-Forum!
Verwende pyodbc
http://pyodbc.sourceforge.net/. Das funktioniert besser als die dbi-Variante.
Code: Alles auswählen
conn = pyodbc.connect("DRIVER=Microsoft Access Driver (*.mdb);UID=admin;DBQ=C:\\Test.accdb")
mfg
Gerold

Verfasst: Freitag 28. September 2007, 12:59
von Aquerias
Hallo Gerold,
danke für die schnelle Antwort.
Ich glaube es hat funktioniert. Die Fehlermeldung erscheint nicht mehr.
Allerdings fehlen mir wohl noch ein paar Grundlagen z.B. weiß ich nicht
für was .cursor() da ist.
Kennst Du ein gutes deutschsprachiges Tutorial, dass einem zeigt wie man
mit Python Daten aus Access abfragt?
Gru0
Aquerias
Verfasst: Freitag 28. September 2007, 13:25
von gerold
Aquerias hat geschrieben:
Allerdings fehlen mir wohl noch ein paar Grundlagen z.B. weiß ich nicht für was .cursor() da ist.
Hallo Aquerias!
http://www.python-forum.de/topic-11615.html
mfg
Gerold

Verfasst: Montag 1. Oktober 2007, 08:22
von Aquerias
Hallo,
ich habe Deine Anleitung durchgelesen und versucht einiges davon anzuwenden.
Mein Quellcode sieht bisher so aus:
>>> import pyodbc
>>> conn = pyodbc.connect("DRIVER=Microsoft Access Driver (*.mdb);UID=admin;DBQ=C:\\Test.mdb")
>>> def select_countries(conn):
... sql="""
... SELECT ContinentID, CountryCode, CountryNameDE
... FROM Countries
... ORDER BY ID
... """
...
>>> cur=conn.cursor()
>>> cur.execute(select_countries)
Danach bekomme ich folgende Fehlermeldung:
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
TypeError: The first argument to execute must be a string or unicode query.
Was genau mache ich falsch?
Bezieht sich "The first argument" auf den Inhalt meiner Tabelle?
Ich hoffe mir kann jemand helfen.
Verfasst: Montag 1. Oktober 2007, 08:38
von gerold
Hallo Aquerias!
Du hast dich nur verschrieben:
mfg
Gerold
PS:
http://www.python-forum.de/faq.php#21
Verfasst: Montag 1. Oktober 2007, 08:50
von Aquerias
Danke für die Antwort,
leider bekomme ich trotzdem eine Fehlermeldung.
Code
Code: Alles auswählen
>>> import pyodbc
>>> conn = pyodbc.connect("DRIVER=Microsoft Access Driver (*.mdb);UID=admin;DBQ=C:\\Test.mdb")
>>> def select_countries(conn):
... sql="""
... SELECT ContinentID, CountryCode, CountryNameDE
... FROM Countries
... ORDER BY ID
... """
...
>>> cur=conn.cursor()
>>> cur.execute(sql)
Fehlermeldung:
Code: Alles auswählen
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
NameError: name 'sql' is not defined
Muss ich nicht die Funktion "select_countries" aufrufen, damit cur.execute weis was er holen soll?
Gruß Aquerias
Verfasst: Montag 1. Oktober 2007, 09:00
von gerold
Aquerias hat geschrieben:leider bekomme ich trotzdem eine Fehlermeldung.
Hallo Aquerias!
Die Zeilen 10 und 11 müssen ebenfalls eingerückt werden.
Das sind Schlampigkeitsfehler.
mfg
Gerold
