Programowanie w języku Python

MySQLdb, czyli MySQL w Pythonie

W Pythonie mamy kilka bibliotek do obsługi bazy MySQL - najpopularniejszą i najlepszą z nich jest MySQLdb i to o niej traktuje ten tekst. Ciekawostkę może stanowić fakt, iż jest używana w takich projektach jak Django, Zope czy SQLAlchemy.

Spis treści

          1 Instalacja MySQLdb
          2 Połączenie z bazą
          3 Pobieranie rekordów z bazy
          4 Wstawianie/modyfikacja danych do bazy

Instalacja MySQLdb


Bibliotekę można ściągnąć z tej strony. W Windowsie można wziąć paczkę dla Win32 z graficznym instalatorem, ja jednak skupię się na instalacji "ze źródeł". Pobieramy archiwum tar.gz i następnie:

$ tar zxvf MySQL-python-*
$ cd MySQL-python-*
$ python setup.py build
$ python setup.py install

Odpalamy Pythona i sprawdzamy czy wszystko jest ok:

>>> import MySQLdb
>>>

Połączenie z bazą


Służy do tego metoda connect. Można ją zainicjować na kilka sposobów:

conn = MySQLdb.connect("host", "user", "haslo", "baza")
conn = MySQLdb.connect(host="host", user="user", passwd="haslo", db="baza")
conn = MySQLdb.connect(read_default_file="/etc/mysql/myapp.cnf")

Dodatkowo istnieją dodatkowe opcje, m.in. compress=1 - włącza kompresję gzip; use_unicode=1 - zwraca dane jako obiekty unicode. Po więcej odsyłam do dokumentacji.

Pobieranie rekordów z bazy


Stwórzmy pierw testową tabelkę w bazie danych:

CREATE TABLE users (
  id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  nick VARCHAR(150),
  pass VARCHAR(150)
);
INSERT INTO users VALUES('', 'coldpeer', 'tajne');
INSERT INTO users VALUES('', 'bohun', 'xxx');

I przykładowy kod:

import MySQLdb
 
conn = MySQLdb.connect("localhost", "user", "haslo", "testy")
 
c = conn.cursor()
c.execute("SELECT nick FROM users")
print c.fetchall()

Wynik będzie następujący:

(('coldpeer',), ('bohun',))

Aby odwołać się do wartości pierwszego rekordu, czyli coldpeer:

print c.fetchall()[0][0]
# lub
print c.fetchone()[0]

Do drugiego zaś (bohun):

c = conn.cursor()
c.execute("SELECT nick FROM users")
print c.fetchall()[1][0]

Aby pobrać wybraną ilość pól:

print c.fetchmany(ile)

Pobierzmy teraz wszystkie pola. Kilka przykładów:

print c.fetchall()

Wynik:

((1L, 'coldpeer', 'tajne'), (2L, 'bohun', 'xxx'))

Liczba pobranych wierszy:

print c.rowcount

A teraz parę przykładów iteracji:

c = conn.cursor()
c.execute("SELECT * FROM users")
for rec in c.fetchall():
    print "ID: %d\nNick: %s\nHaslo: %s\n----" % (
        rec[0], rec[1], rec[2])
 
# druga wersja        
for id, nick, haslo in c.fetchall():
    print "ID: %d\nNick: %s\nHaslo: %s\n----" % (
        id, nick, haslo)
 
# trzecia wersja
for i in range(c.rowcount):
    rec = c.fetchone()
    print "ID: %d\nNick: %s\nHaslo: %s\n----" % (
        rec[0], rec[1], rec[2])

Wynik:

ID: 1
Nick: coldpeer
Haslo: tajne
----
ID: 2
Nick: bohun
Haslo: xxx
----


Aby wprowadzić do zapytania jakąś wartość np. podaną przez użytkownika:

c.execute("SELECT nick FROM users WHERE pass = %s", ("xxx"))
 
# inny przyklad, gratis jak robic wielolinijkowe zapytania
c.execute("""
SELECT
  nick
FROM
  users
WHERE
    id = %s
  AND
    pass = %s
""",(2, "xxx"))

Zalecane jest, aby ze nie używać tutaj operatora %, tj. c.execute(sql%wartosci). Zapytanie oczywiście pobierze użytkownika o nicku bohun:

(('bohun',),)

Wstawianie/modyfikacja danych do bazy


Naturalnie, używamy tutaj zapytań INSERT, UPDATE, ALTER itd. odzianych w metodzie execute:

c = conn.cursor()
c.execute("INSERT INTO users VALUES('', 'albin', 'yyy')")

Czasem zachodzi potrzeba użycia np. kilku INSERT-ów. Jeśli różnią się one tylko wstawianymi danymi, to zamiast pisać:

c.execute("INSERT INTO users VALUES('',%s,%s)", ('user1', 'haslo1'))
c.execute("INSERT INTO users VALUES('',%s,%s)", ('user2', 'haslo2'))

Można skorzystać z metody executemany:

c.executemany("INSERT INTO users VALUES('',%s,%s)",
    ( ('user1', 'haslo1'), ('user2', 'haslo2') ))

Dostępne są też transakcje, tj. conn.begin(), conn.commit() i conn.rollback().

Więcej na temat biblioteki MySQLdb można znaleźć m.in. w dokumentacji API.