float + datenbank
float + datenbank
Hallo zusammen,
ne absolute Anfängerfrage aber ich find dazu nix :
Ich lese per ADO-Recordset aus einer SQL-Server Datenbank diverse Felder. Alles klappt meiner Meinung..... Nur :
sumU = rsK.Fields("Umsatz").Value
einproz = sumU / 100
liefert die Fehlermeldung :
TypeError: unsupported operand type(s) for /: 'tuple' and 'int'
Das Feld "Umsatz" ist ein Float Wert in der Datenbank..... warum wird dies als "tuple" interpretiert???
Vielen Dank für eure Hilfe!!
Gruss
Markus
ne absolute Anfängerfrage aber ich find dazu nix :
Ich lese per ADO-Recordset aus einer SQL-Server Datenbank diverse Felder. Alles klappt meiner Meinung..... Nur :
sumU = rsK.Fields("Umsatz").Value
einproz = sumU / 100
liefert die Fehlermeldung :
TypeError: unsupported operand type(s) for /: 'tuple' and 'int'
Das Feld "Umsatz" ist ein Float Wert in der Datenbank..... warum wird dies als "tuple" interpretiert???
Vielen Dank für eure Hilfe!!
Gruss
Markus
"Humor ist der Knopf, der verhindert, dass einem der Kragen platzt"
Re: float + datenbank
macmark hat geschrieben:Das Feld "Umsatz" ist ein Float Wert in der Datenbank..... warum wird dies als "tuple" interpretiert???
Weil ADO an der stelle eine Tupel zurückgibt, darum!
Mach mal
Code: Alles auswählen
print sumU
Edit: Achja, nicht zu vergessen das obligatorische "Willkommen"

My god, it's full of CARs! | Leonidasvoice vs Modvoice
stell dir die Datenbank vereinfacht als Tabelle vor:
Primärschlüssel | Umsatz | Spalte3 | Spalte 4| ...
diese Tabelle kann quasi unendlich viele Zeilen (Datensätze) enthalten. Mit:
erhälst du in einer Liste abgelegt alle Zeilen von Umsatz zB:
sumU = ['125.57','3415,23',...]
auch wenn du nur eine Zahl drin hast, liegt diese Zahl trotzdem in einer Liste, die in dem Fall nur ein Element enthält. Wie Leonidas schon richtig geschrieben hat, greifst du auf das 1. Element der Liste mit sumU[0] zu. Damit erhälst du dann die "Zahl" als float.
Also:
Primärschlüssel | Umsatz | Spalte3 | Spalte 4| ...
diese Tabelle kann quasi unendlich viele Zeilen (Datensätze) enthalten. Mit:
Code: Alles auswählen
sumU = rsK.Fields("Umsatz").Value
erhälst du in einer Liste abgelegt alle Zeilen von Umsatz zB:
sumU = ['125.57','3415,23',...]
auch wenn du nur eine Zahl drin hast, liegt diese Zahl trotzdem in einer Liste, die in dem Fall nur ein Element enthält. Wie Leonidas schon richtig geschrieben hat, greifst du auf das 1. Element der Liste mit sumU[0] zu. Damit erhälst du dann die "Zahl" als float.
Also:
Code: Alles auswählen
sumU = rsK.Fields("Umsatz").Value
einproz = sumU[0] / 100.
macmark hat geschrieben:Hast du evtl. ne Website wo erklärt wird warum das so ist?? Zu "Python + ADO" in Google findet sich nix.
Also ich habe das und das gefunden.
Warum da eine Tupel rauskommt kann ich dir auch nicht 100%ig sagen, das liegt einfach daran, wie die ADO-API ist.. die ist nunmal afair nicht PEP 249, dh. DB-API 2 kompatibel, so haben die Macher von ADO einfach entschieden (und auch mit der DB-API 2 wäre das so wie es ist, eine Liste oder Tupel). Warscheinlich meinten sie, dass jede SQL-Anweisung mehrere Werte ausgeben könnte, deswegen wäre es sinnvoller, an der Stelle einen Container (Tupel eben) auszugeben, in dem dann die eigentlichen Daten stecken.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Cool... Danke!!
Das Beispiel auf http://www.ecp.cc/ado_examples.shtml :
>>> y = r.Fields.Item(2).Value
>>> y
(0, 850000)
>>> z = y[1]/10000
>>> print 'this information costs $%.*f' % (2,z)
this information costs $85.00
... ist schon sehr vielsagend!!! Wenn man von VB auf Python umsteigt ist das recht gewöhnungsbedürftig....
... aber trotzdem ne coole Sprache! 
Das Beispiel auf http://www.ecp.cc/ado_examples.shtml :
>>> y = r.Fields.Item(2).Value
>>> y
(0, 850000)
>>> z = y[1]/10000
>>> print 'this information costs $%.*f' % (2,z)
this information costs $85.00
... ist schon sehr vielsagend!!! Wenn man von VB auf Python umsteigt ist das recht gewöhnungsbedürftig....


"Humor ist der Knopf, der verhindert, dass einem der Kragen platzt"
- gerold
- Python-Forum Veteran
- Beiträge: 5554
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Telfs (Tirol)
- Kontaktdaten:
Leonidas hat geschrieben:Warscheinlich meinten sie, dass jede SQL-Anweisung mehrere Werte ausgeben könnte, deswegen wäre es sinnvoller, an der Stelle einen Container (Tupel eben) auszugeben, in dem dann die eigentlichen Daten stecken.
Hi @all!
Ich bin überfragt, aber eines weiß ich gewiss. Die Anweisung
Code: Alles auswählen
rsK.Fields("Umsatz")
, ob mit oder ohne "Value" sollte den Inhalt des Feldes ausgeben. Und das komplett ohne diesen vorher in ein Tupel zu setzen.
Code: Alles auswählen
rsK.Fields.Item("Umsatz").Value
Sollte sich exakt gleich wie der oben aufgezeigte Code verhalten.
Eventuell hilft es PyWin32 und ADO auf den neuesten Stand zu bringen.
Hier ein Test mit einer Artikeltabelle in einer MS SQL-Datenbank:
Code: Alles auswählen
>>> import win32com.client
>>> conn = win32com.client.Dispatch('ADODB.Connection')
>>> DSN = "Provider=SQLOLEDB.1;Password=IrgendeinPasswort;Persist Security Info=True;User ID=SWA;Initial Catalog=dbSWALokal;Data Source=(local)"
>>> conn.Open(DSN, "sa", "EinPasswort")
>>> rs = win32com.client.Dispatch('ADODB.Recordset')
>>> rs.Open("Select top 10 * from tArtikel", conn, 1, 3)
>>> print rs.Fields("ArtikelNr")
1
>>> print rs.Fields("ArtikelNr").Value
1
>>> print rs.Fields.Item("ArtikelNr").Value
1
>>> print rs.Fields.Item("ArtikelNr")
1
>>> rs.MoveNext()
>>> print rs.Fields.Item("ArtikelNr")
2
>>> print rs.Fields("VKP_Brutto")
0.0
>>> rs.Close()
>>> conn.Close()
>>>
Wie man an print rs.Fields("VKP_Brutto") sieht, wird eine Float-Zahl auch wirklich als Float-Zahl und nicht in einem Tupel ausgegeben.
@macmark: Das ist das normale Verhalten von ADO. Es stimmt also leider irgendetwas bei dir nicht.
lg
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
gerold hat geschrieben:Eventuell hilft es PyWin32 und ADO auf den neuesten Stand zu bringen.
@macmark: Das ist das normale Verhalten von ADO. Es stimmt also leider irgendetwas bei dir nicht.
.... mmmmhhh!! Sollte ich beides auf einem aktuellen Stand haben. PyWin32 habe ich erst vor 2 Wochen runtergeladen : pywin32-208.win32-py2.4 und ADO ist auch auf dem aktuellen Stand! Verwende auf meiner Dev-Maschine den SQL-Server 2005 Express.
Ich probiers mal auf anderen Maschinen..... vielleicht hängt es ja damit zusammen.
Poste auf jeden Fall das Ergebnis....
Gruss
Markus
"Humor ist der Knopf, der verhindert, dass einem der Kragen platzt"
- gerold
- Python-Forum Veteran
- Beiträge: 5554
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Telfs (Tirol)
- Kontaktdaten:
Buell hat geschrieben:Code: Alles auswählen
sumU = rsK.Fields("Umsatz").Value
erhälst du in einer Liste abgelegt alle Zeilen von Umsatz zB:
sumU = ['125.57','3415,23',...]
Hi Buell!
Leider muss ich dich da unterbrechen. ADO kennt einen Datensatzzeiger, der nach dem Ausführen einer SQL-Abfrage direkt auf dem ersten Datensatz liegt. Mit rs.MoveNext() wird der DS-Zeiger zum nächsten Datensatz verschoben.
Ist der DS-Zeiger auf der ersten Zeile, dann werden nur Werte der ersten Zeile zurück gegeben. Auf keinen Fall wird eine Liste aller Werte eines Feldes mit rs.Fields("Feldname") zurück gegeben. Was der Normalfall ist, sollte mein Beispiel im letzten Beitrag von mir ziemlich gut aufzeigen.
@macmark: Ein bischen mehr Code von dir würde uns den Fehler sicher schnell finden lassen.
lg
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
- gerold
- Python-Forum Veteran
- Beiträge: 5554
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Telfs (Tirol)
- Kontaktdaten:
macmark hat geschrieben:Verwende auf meiner Dev-Maschine den SQL-Server 2005 Express.
Hi Markus!
Alles was ich bis jetzt geschrieben habe, gilt bis zum SQL-Server 2000. Ob sich ADO beim SQL-Server 2005 Express anders verhält, das kann ich nicht sagen, da ich beim Umsteigen auf PostgreSQL bin und wahrscheinlich den Rest meines Lebens kein Bedarf mehr für den 2005er besteht.
Außerdem setze ich derzeit die ADO-Version 2.8 ein. Vielleicht verhält sich eine neuere Version anders.
mfg
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
ok..... hier grob der Code der derzeit klappt :
Edit (Leonidas): Code in Python-Tags gesetzt.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from Tkinter import *
import sys
import win32com.client
root = Tk()
lblstatus=StringVar(root)
root.l=Label(root,textvariable=lblstatus)
root.l.pack()
DSN = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog="
DSN = DSN + "TestDB;Data Source=SQLEXPRESS;Use Procedure for Prepare=1"
DSN = DSN + ";Auto Translate=True;Packet Size=4096;Workstation ID="
DSN = DSN + "DEV;Use Encryption for Data=False;"
DSN = DSN + "Tag with column collation when possible=False"
lblstatus.set("DB öffnen .... ")
root.update()
monat = 1
monat = 2006
conn = win32com.client.Dispatch(r'ADODB.Connection')
conn.Open(DSN)
sumU = 0
sqlk = " SELECT Sum(Umsatz1)+Sum(Umsatz2)+Sum(Umsatz3) AS Umsatz "
sqlk = sqlk + " FROM tbStatistik "
sqlk = sqlk + " where month(Datum) = " + str(monat)
sqlk = sqlk + " and year(Datum) = " + str(jahr)
rsK = win32com.client.Dispatch(r'ADODB.Recordset')
rsK.Open(sqlk, conn, 1, 3)
if not rsK.eof:
sumU = rsK.Fields("Umsatz").Value[1] / 10000
rsK.Close()
einproz = sumU / 100
print einproz
print sumU
conn.Close()
lblstatus.set("Fertig .... ")
root.update()
Edit (Leonidas): Code in Python-Tags gesetzt.
"Humor ist der Knopf, der verhindert, dass einem der Kragen platzt"
- gerold
- Python-Forum Veteran
- Beiträge: 5554
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Telfs (Tirol)
- Kontaktdaten:
macmark hat geschrieben:Code: Alles auswählen
sumU = rsK.Fields("Umsatz").Value[1] / 10000
Hi macmark!
Es lässt mir keine Ruhe -- Kann es wirklich sein, dass es von einer SQL-Server Version zur nächsten, so einen extremen Unterschied im Verhalten gibt?
Was kommt eigentlich als Ergebnis dieses Programmes raus? (Vielleicht musst du es noch anpassen, falls ich irgendwo noch einen Syntaxfehler drinnen habe.)
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
import win32com.client
DSN = (
"Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;"
"Initial Catalog=TestDB;Data Source=SQLEXPRESS;Use Procedure for Prepare=1;"
"Auto Translate=True;Packet Size=4096;Workstation ID=DEV;"
"Use Encryption for Data=False;Tag with column collation when possible=False"
)
monat = 1
monat = 2006
conn = win32com.client.Dispatch(r'ADODB.Connection')
conn.Open(DSN)
rsK = win32com.client.Dispatch(r'ADODB.Recordset')
sqlk = \
"""SELECT
Sum(Umsatz1) as sum_umsatz1,
Sum(Umsatz2) as sum_umsatz2,
Sum(Umsatz3) as sum_umsatz3,
Sum(Umsatz1) + Sum(Umsatz2) + Sum(Umsatz3) AS sum_umsatz
FROM
tbStatistik
WHERE
(month(Datum) = %s) And
(year(Datum) = %s)
""" % (monat, jahr)
rsK.Open(sqlk, conn, 1, 3)
print "1: %s" % rsk.Fields("sum_umsatz1")
print "2: %s" % rsk.Fields("sum_umsatz2")
print "3: %s" % rsk.Fields("sum_umsatz3")
print "sum: %s" % rsk.Fields("sum_umsatz")
rsK.Close()
conn.Close()
mfg
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Hi Gerold,
das Thema hat mich nicht so ganz losgelassen und ich habe mit dem SQL-Server mal folgendes getestet :
Mit Testdaten versorgt kam folgendes dabei raus :
testdecimal: 12,34
testfloat: 14.56
testmoney: (0, 132000)
testnumeric: 14,4
testreal: 12.6000003815
testsmallmoney: (0, 608000)
D.h. nur bei einigen Datentypen reagiert wird das Ergebnis als Tuple zurückgegeben. Bei der mir vorliegenden Datenbank waren die Felder wirklich als Money definiert. In deiner Datenbank sind die wahrscheinlich anders definiert. Daher also der Unterschied.
Wer Lust hat kann das ja auch mal bei seiner DB simulieren ob sich Python/ADO da ähnlich verhält.
Schönen Gruss
Markus
das Thema hat mich nicht so ganz losgelassen und ich habe mit dem SQL-Server mal folgendes getestet :
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#Tabelle im SQL-Server
#CREATE TABLE [testtab](
# [testdecimal] [decimal](18, 2) NULL,
# [testfloat] [float] NULL,
# [testmoney] [money] NULL,
# [testnum] [numeric](18, 2) NULL,
# [testreal] [real] NULL,
# [testsm] [smallmoney] NULL,
# [id] [int] NULL
#) ON [PRIMARY]
import win32com.client
DSN = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog="
DSN = DSN + "TestDB;Data Source=SQLEXPRESS"
conn = win32com.client.Dispatch(r'ADODB.Connection')
conn.Open(DSN)
sql = 'select id, testdecimal, testfloat, testmoney, testnum, testreal, testsm from testtab order by id '
rs = win32com.client.Dispatch(r'ADODB.Recordset')
rs.Open(sql, conn, 1, 3)
if not rs.eof:
print "testdecimal: %s" % rs.Fields("testdecimal")
print "testfloat: %s" % rs.Fields("testfloat")
print "testmoney: %s" % rs.Fields("testmoney")
print "testnumeric: %s" % rs.Fields("testnum")
print "testreal: %s" % rs.Fields("testreal")
print "testsmallmoney: %s" % rs.Fields("testsm")
rs.Close()
conn.Close()
Mit Testdaten versorgt kam folgendes dabei raus :
testdecimal: 12,34
testfloat: 14.56
testmoney: (0, 132000)
testnumeric: 14,4
testreal: 12.6000003815
testsmallmoney: (0, 608000)
D.h. nur bei einigen Datentypen reagiert wird das Ergebnis als Tuple zurückgegeben. Bei der mir vorliegenden Datenbank waren die Felder wirklich als Money definiert. In deiner Datenbank sind die wahrscheinlich anders definiert. Daher also der Unterschied.


Wer Lust hat kann das ja auch mal bei seiner DB simulieren ob sich Python/ADO da ähnlich verhält.
Schönen Gruss
Markus
"Humor ist der Knopf, der verhindert, dass einem der Kragen platzt"
Wer ist online?
Mitglieder in diesem Forum: 0 Mitglieder