Seite 1 von 1
Felltnamen und Datentyp von SQL Abfragen gesucht
Verfasst: Freitag 8. April 2016, 07:46
von hans
Ich suche nach einer Möglichkeit, in einer SQLite den Datentyp und Feldnamen gemäss Datenbankdefinition herauszufinden. Im Internet fand ich dieses Beispiel (von mir um r=sqlite3.Row / print(r.keys()) ergänzt). Frage mich was bei r.keys() für ein Argument notwendig ist. Kann ich der Dokumentation nicht entnehmen.
Code: Alles auswählen
import sqlite3
from idlelib.PyShell import main
from datetime import date, datetime
def main():
db = sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
#db = sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES)
c = db.cursor()
c.execute('''CREATE TABLE example(id INTEGER PRIMARY KEY, created_at DATE)''')
# Insert a date object into the database
today = date.today()
c.execute('''INSERT INTO example(created_at) VALUES(?)''', (today,))
db.commit()
# Retrieve the inserted object
c.execute('''SELECT created_at FROM example''')
r=sqlite3.Row
row = c.fetchone()
print('The date is {0} and the datatype is {1}'.format(row[0], type(row[0])))
# The date is 2013-04-14 and the datatype is <class 'datetime.date'>
print(row[0])
print(type(row[0]))
print(row[0].isoformat())
print(r.keys())
db.close()
if __name__ == '__main__':
main()
Fehlermeldung:
Code: Alles auswählen
Traceback (most recent call last):
File "/home/nor/projects/spielwiese/detect.py", line 32, in <module>
main()
File "/home/nor/projects/spielwiese/detect.py", line 25, in main
print(r.keys())
TypeError: descriptor 'keys' of 'sqlite3.Row' object needs an argument
Re: Felltnamen und Datentyp von SQL Abfragen gesucht
Verfasst: Freitag 8. April 2016, 08:20
von Sirius3
@hans: Programmieren ist nicht Raten. Wenn Du irgendwelche Beispiele um zufällige Zeilen ergänzt, wirst Du keinen Erfolg haben. Methoden brauchen immer eine Instanz, mit der sie arbeiten. Daher ruft man auch nie (selten) die Methoden der Klasse auf. Das Beispiel zu Row.keys in der Dokumentation ist doch eigentlich selbsterklärend.
Warum importierst Du main aus einem abstrusen Modul, um es gleich zwei Zeilen später zu überschreiben?
PS: Ich würde ja über cursor.description gehen.
Re: Felltnamen und Datentyp von SQL Abfragen gesucht
Verfasst: Freitag 8. April 2016, 08:40
von DasIch
r ist eine Klasse und du rufst auf dieser eine Instanzmethode auf. Die Methode bekommt deswegen self nicht übergeben, über dieses fehlende Argument wird sich in der Fehlermeldung beschwert.
Deine Ergänzung macht allerdings schon grundsätzlich keinen Sinn. Schau dir nochmal die Dokumentation zum sqlite3 Modul an. Das ist allerdings auch letztendlich egal weil schon der Ansatz dir nicht hilft an das Schema zu kommen.
SQLite speichert Informationen zu Tabellen in einer SQLITE_MASTER Tabelle und du kannst Informationen über die Spalten mit `PRAGMA TABLE_INFO('table')` bekommen.
Code: Alles auswählen
import sqlite3
connection = sqlite3.connect(':memory:')
connection.row_factory = sqlite3.Row
connection.execute("""
CREATE TABLE example (
id INTEGER PRIMARY KEY,
created_at DATE
)
""")
sqlite_master_columns = connection.execute('SELECT * FROM SQLITE_MASTER').fetchone().keys()
print('SQLITE_MASTER columns: {}'.format(sqlite_master_columns))
table_names = [
row[0] for row in
connection.execute('SELECT tbl_name FROM SQLITE_MASTER WHERE type = "table"')
]
print('Table names: {}'.format(table_names))
for table_name in table_names:
print('Table {}'.format(table_name))
for row in connection.execute('PRAGMA TABLE_INFO({})'.format(table_name)):
print('- Column: {0[name]}, type: {0[type]}'.format(row))
Re: Feldnamen und Datentyp von SQL Abfragen gesucht
Verfasst: Freitag 8. April 2016, 11:20
von hans
@Sirius3: Verstehe einer die Dokumentation

Einige simple Beispiele (in der Doku) würden mehr Klarheit schaffen. Hat aber auch was gutes. Habe die Wirkung von
entdeckt. Kann man dann im Editor immer mal wieder aufrufen.
@DasIch: Hilft schon einmal weiter, aber das sind Tabellen in der Datenbank. Ich möchte das jedoch für eine SQL Abfrage definieren, die ich noch nicht kenne. Angenommen jemand tippt folgendes ein
Code: Alles auswählen
select
sum(Feld_a+Feld_b) as AB,
Feld_c as NAME
from TestTable
where ........
order by NAME
group by NAME
Ich pfeiffe mir die Doku noch mal rein. Mal sehen ob ich es gelöst bekomme. Es geht insbesondere um die Datentypen. Feldnamen bekomme ich schon heraus.
Re: Felltnamen und Datentyp von SQL Abfragen gesucht
Verfasst: Freitag 8. April 2016, 11:55
von Sirius3
Es gibt einige simple Besispiele.
Re: Feldnamen und Datentyp von SQL Abfragen gesucht
Verfasst: Freitag 8. April 2016, 15:43
von hans
ahhh, Sirius3, lass mich an deinem Wissen teilhaben. Das was ich gefunden habe, war nicht so simpel.Ich bin einmal von DasIch's Skript ausgegangen. Nur kam ich da an connection.description nicht heran. Ein anderes Problem bestand darin, dass connection.decription erst nach einem fetchone, fetchall, fetchmany existiert. Nutzt man fetchone.keys() fehlt dir der erste Datensatz. Also habe ich das Skript einmal umgebaut.
Code: Alles auswählen
import sqlite3
from datetime import date
connection = sqlite3.connect('file:/usr/data/digikam/digikam4.db?mode=ro',
detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES, uri=True)
connection.row_factory = sqlite3.Row
cursor=connection.cursor()
sqlresult=cursor.execute('SELECT * FROM albumroots')
#query_columns = cursor.fetchone().keys()
#print('**',query_columns,'**')
i=0
fName = None
for row in sqlresult.fetchall():
print('\n\nrecord #:{0} ***********'.format(i))
j = 0
for item in row:
if fName == None:
k = 0
fName={0:''}
for field in cursor.description:
fName[k] = field[0]
k +=1
s1 = str(type(item)).replace("<class '",'').replace("'>",'')
s2 = '*** FiedName {0} >> Data {1} >> Type {2} ***'.format(fName[j],item,s1)
print(s2)
j +=1
i +=1
connection.description enthält immer die Spaltennamen des zuletzt verarbeiteten Spaltennamens. Es muss erst irgend ein fetch.... ausgeführt worden sein, um an die Spaltennamen zu kommen.
Das Ergebnis sieht dann so aus
Code: Alles auswählen
record #:0 ***********
*** FiedName id >> Data 1 >> Type int ***
*** FiedName label >> Data Collection 02 >> Type str ***
*** FiedName status >> Data 0 >> Type int ***
*** FiedName type >> Data 2 >> Type int ***
*** FiedName identifier >> Data volumeid:?uuid=201e6d5a1e6d2a4c >> Type str ***
*** FiedName specificPath >> Data /Data/GIMP >> Type str ***
record #:1 ***********
*** FiedName id >> Data 2 >> Type int ***
*** FiedName label >> Data Collection 01 >> Type str ***
*** FiedName status >> Data 0 >> Type int ***
*** FiedName type >> Data 2 >> Type int ***
*** FiedName identifier >> Data volumeid:?uuid=1adc8962dc893951 >> Type str ***
*** FiedName specificPath >> Data /Data/GIMP >> Type str ***
>>>
Zur Probe nochmals die Abfrage geändert:
Ausgabe
Code: Alles auswählen
record #:0 ***********
*** FiedName id >> Data 1 >> Type int ***
*** FiedName label >> Data Collection 02 >> Type str ***
*** FiedName ST >> Data 0 >> Type int ***
record #:1 ***********
*** FiedName id >> Data 2 >> Type int ***
*** FiedName label >> Data Collection 01 >> Type str ***
*** FiedName ST >> Data 0 >> Type int ***
Jetzt heißt das Feld ST und nicht mehr Status.
Re: Felltnamen und Datentyp von SQL Abfragen gesucht
Verfasst: Freitag 8. April 2016, 17:21
von Sirius3
@hans: cursor.description ist sofort nach dem execute verfügbar, ohne irgendein fetch. Wenn Du in einer for-Schleife einen Index brauchst, nimm enumerate und zähle nicht händisch. Ein Dictionary das die Keys 0, 1, 2, ... hat, wäre lieber eine Liste geworden. Statt den Namen eines Typs aus seiner String-Repräsentation herauszuparsen gibt es __name__. fName ist ein schlechter Name, weil niemand weiß, was f bedeutet.
Alles in Allem kommt das dabei raus:
Code: Alles auswählen
cursor = connection.cursor()
cursor.execute('SELECT * FROM albumroots')
field_names = [d[0] for d in cursor.description]
for idx, row in enumerate(cursor):
print('\n\nrecord #:{0} ***********'.format(idx))
for field_name, value in zip(field_names, row):
print('*** FieldName {0} >> Data {1} >> Type {2} ***'.format(
field_name, value, type(value).__name__
))