SQL

Abfrage von Autoren der Uni-Bibliografie der TUC

#!/usr/bin/env python3
# -*- coding: utf8 -*-
#
# Abfrage von Autoren der Uni-Bibliografie
#
# s.a.
#   Python 3 and MySQL
#   https://stackoverflow.com/questions/4960048/python-3-and-mysql
#
#   pip install mysqlclient
#
# 22.1.2018

from __future__ import print_function
import MySQLdb, MySQLdb.cursors

# Daten für den Zugriff auf die Datenbank
db         = 'unibiblio'
db_timeout = 5
db_user    = 'opusread'
db_host    = 'opac.bibliothek.tu-chemnitz.de'
db_pass    = 'opusread'

# unser SELECT
stmt = '''
select
  source_opus,
  creator_name,
  creator_kst
from
  opus_autor
order by
  source_opus,
  reihenfolge
limit 10
'''

# Verbindung zur Bibliografie-Datenbank öffnen
dbh = MySQLdb.connect(host = db_host, user = db_user, passwd = db_pass,
                      db = db, connect_timeout = db_timeout)

# Abfrage ohne Cursor ausführen und das Resultat holen; use_result() belässt es
# auf dem Server, man holt es zeilenweise mit result.fetch_row() ab; mit
# store_result() holt man das Ergebnis geschlossen auf den Klienten
dbh.query(stmt)
result = dbh.use_result()

print('result', dir(result), '\n')

# Resultat-Zeilen sukzessive mit fetch_row() holen
print('ohne Cursor')
while True:
    result_zeile = result.fetch_row()
    print(repr(result_zeile))
    if not result_zeile:
        # keine Daten mehr da
        break

# einen Cursor anlegen
cursor = dbh.cursor()
# falls man intern use_result() statt store_result() nutzen und so das Resultat
# auf dem MySQL-Server statt dem Klienten speichern will, muss man die
# Cursor-Klasse SSCursor verwenden:
#cursor = dbh.cursor(cursorclass = MySQLdb.cursors.SSCursor)

print('\ncursor', dir(cursor))
print('\ncursor.arraysize %d\n' % cursor.arraysize, end=' ')

# Abfrage nochmal ausführen
count = cursor.execute(stmt)
print('\ncount = %d' % count)

# über dem Cursor iterieren
print('iteriere über dem Cursor')
for row in cursor:
    print(repr(row))

# nochmal mit fetch_one()
count = cursor.execute(stmt)
print('\ncount = %d' % count)

print('fetchone()')
while True:
    row = cursor.fetchone()
    print(repr(row))
    if not row:
        break

# und nochmal mit fetch_many()
count = cursor.execute(stmt)
print('\ncount = %d' % count)

print('fetchmany()')
while True:
    rows = cursor.fetchmany()
    print(repr(rows))
    if not rows:
        break

# und nochmal mit fetch_many(7)
count = cursor.execute(stmt)
print('\ncount = %d' % count)

print('fetchmany(7)')
while True:
    rows = cursor.fetchmany(7)
    print(len(rows), '==>', repr(rows))
    if not rows:
        break

# Verbindung zur Datenbank lösen
dbh.close()

Abfrage von Autoren der Uni-Bibliografie und Ausgabe in eine CSV-Datei

#!/usr/bin/env python3
# -*- coding: utf8 -*-
#
# Abfrage von Autoren der Uni-Bibliografie und Ausgabe in eine CSV-Datei
#
# anschließend wird die generierte CSV-Datei eingelesen und "schön" formatiert
# angezeigt
#
# s.a.
#   Python 3 and MySQL
#   https://stackoverflow.com/questions/4960048/python-3-and-mysql
#
#   pip install mysqlclient
#
# 22.1.2018

from __future__ import print_function
import MySQLdb, csv

# Daten für den Zugriff auf die Datenbank
db         = 'unibiblio'
db_timeout = 5
db_user    = 'opusread'
db_host    = 'opac.bibliothek.tu-chemnitz.de'
db_pass    = 'opusread'

# die Liste der abzufragenden SQL-Felder
fields = (
  'source_opus',
  'creator_name',
  'creator_kst',
)

# Select-Statement für die Abfrage; die Liste der Felder wird eingefügt
stmt = '''
select
  %s
from
  opus_autor
order by
  source_opus,
  reihenfolge
limit 10
''' % ','.join(fields)

# Verbindung zur Bibliografie-Datenbank öffnen
dbh = MySQLdb.connect(host = db_host, user = db_user, passwd = db_pass,
                      db = db, connect_timeout = db_timeout)

# einen DictCursor für unsere SQL-Abfragen erzeugen, der den Zugriff auf die
# Felder über die Feldnamen gestattet
cursor = dbh.cursor(MySQLdb.cursors.DictCursor)

# gemäß der Empfehlung unter
# http://www.php.net/manual/de/function.mysql-set-charset.php#86455
# die Verbindung konsequent auf UTF8 umstellen
cursor.execute("SET character_set_results = 'utf8', character_set_client = 'utf8',"
               "character_set_connection = 'utf8',"
               "character_set_database = 'utf8', character_set_server = 'utf8'")

# Abfrage starten
cursor.execute(stmt)

# Generatorfunktion, die schrittweise die CSV-Zeilen liefert
def data_gen(cursor):
    # als 1. Zeile liefern wir das Tupel der Felder
    csv_fields = 'source_opus', 'creator_kst', 'creator_name'
    yield csv_fields
    # nun der Reihe nach die abgefragten Sätze zurückgeben; wir liefern die Liste
    # der Feldinhalte gemäß obiger Feldreihenfolge
    for line in cursor:
        yield [line[csv_field] for csv_field in csv_fields]

# Name der CSV-Datei
csv_filename = 'liste.csv'

# die Datenbank satzweise lesen und in die CSV-Datei ausgeben
with open(csv_filename, 'w') as csv_file:
    # writerows gibt alle Elemente der angegebenen Sequenz (hier die von der
    # Generatorfunktion erzeugten Zeilen/Sequenzen) in die CSV-Datei aus
    csv.writer(csv_file).writerows(data_gen(cursor))

# nun die gerade generierte CSV-Datei einlesen und "schön" ausgeben
with open(csv_filename) as csv_file:
    # zuerst Zeile 1 einlesen und in die Feldnamen aufspalten
    #
    # - csv_file.readline() liest die 1. Zeile aus der CSV-Datei
    # - wir generieren einen CSV-Reader und übergeben ihm als zu lesende Sequenz
    #   eine einelementige Liste, die nur die 1. Zeile der CSV-Datei enthält
    # - next() liefert das nächste Element eines Iterators und holt somit das
    #   Ergebnis des CSV-Readers ab
    fieldnames = next(csv.reader([csv_file.readline()]))

    # die maximale Länge der Feldnamen ermitteln
    max_len = max(len(fn) for fn in fieldnames)

    # daraus einen passenden Formatstring erstellen, in den max_len als Länge des
    # String-Platzhalters %s einfließt
    fmt = '%%%ds: %%s' % max_len

    # einen DictReader für die restlichen Zeilen des CSV-Files generieren;
    # durch das obige readline() liefert csv_file hier die Sequenz der CSV-Zeilen
    # ab Zeile 2
    reader = csv.DictReader(csv_file, fieldnames)

    # die CSV-Zeilen durchlaufen
    for line in reader:
        # pro Zeile die Liste der Feldnamen durchgehen
        #print repr(line)
        for fn in fieldnames:
            # jedes Feld formatiert ausgeben
            if 1:
                # Variante 1:
                # der * bei %*s symbolisiert eine dynamische Länge für den
                # String-Platzhalter %s, die wir durch das erste Argument max_len
                # angeben
                print('%*s: %s' % (max_len, fn, line[fn]))
            else:
                # Variante 2:
                # Nutzung des oben erstellten Formatstrings
                print(fmt % (fn, line[fn]))
        print()