263 lines
7.2 KiB
Plaintext
263 lines
7.2 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Datenbankverbindungen mit Python\n",
|
|
"\n",
|
|
"In diesem Notebook lernen wir, wie wir: \n",
|
|
" * eine Verbindung zur Datenbank herstellen\n",
|
|
" * SQL Ausführen (und Parameter aus Python nutzen)\n",
|
|
"\n",
|
|
"Vorraussetzungen hierfür sind:\n",
|
|
" * Grundkenntnisse Python\n",
|
|
" * Grundkenntnisse SQL\n",
|
|
" \n",
|
|
"Die Methoden die für den Zugriff auf die Datenbank nötig sind, sind in der Python Database API Specification v2 [PEP 249](https://www.python.org/dev/peps/pep-0249/) beschrieben.\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Eine Verbindung zur Datenbank herstellen\n",
|
|
"\n",
|
|
"Die Datenbankverbindung wird über das Modul der Datenbank aufgebaut. Dieses Modul verfügt über eine `connect( parameters... )`-Methode. Die genauen Parameter, die eine Datenbank für die Verbindung benötigt, kann jedes Datenbank-Modul selbst festlegen. \n",
|
|
"\n",
|
|
"In unseren Beispiel verwenden wir eine Sqlite3-Datenbank. Der Parameter `:memory:` erzeugt eine Datenbank im Hauptspeicher. Diese Datenbank ist sehr schnell erstellt, aber dafür nicht persistent. Zum erproben der Verbindungsfunktionen ist dies jedoch vollkommen ausreichend. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%run Datenbankzugriff_Util.ipynb # import zu Überprüfung der Übungen\n",
|
|
"\n",
|
|
"# Verbindung mit der Datenbank herstellen\n",
|
|
"import sqlite3\n",
|
|
"conn = sqlite3.connect(':memory:')\n",
|
|
"\n",
|
|
"\n",
|
|
"#import mysql.connector\n",
|
|
"#conn = mysql.connector.connect(\n",
|
|
"# host=\"localhost\",\n",
|
|
"# user=\"yourusername\",\n",
|
|
"# password=\"yourpassword\",\n",
|
|
"# database=\"mydatabase\"\n",
|
|
"#)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## SQL Ausführen\n",
|
|
"\n",
|
|
"SQL-Statements werden mithilfe eines Cursors ausgeführt. Ein Cursor kann auch DML- oder DDL-Anfragen ausführen. Bei DQL-Abfragen können Datensätze mit fetchall() direkt geladen werden. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# DDL\n",
|
|
"cur = conn.cursor()\n",
|
|
"cur.execute('''CREATE TABLE emp(id NUMBER, name VARCHAR(255), sal NUMBER)''')\n",
|
|
"cur.close()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# DML\n",
|
|
"c= conn.cursor()\n",
|
|
"# Daten einfuegen\n",
|
|
"c.execute(\"INSERT INTO emp VALUES (1, 'Smith', 3200)\")\n",
|
|
"c.execute(\"INSERT INTO emp VALUES (2, ?, 2800)\", [(\"Adams\")])\n",
|
|
"c.executemany(\"INSERT INTO emp VALUES (?, ?, ?)\", \n",
|
|
" [(3, \"King\", 5200), (4,\"Johnson\", 3400)])\n",
|
|
"conn.commit();"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Abfrage von Daten (SELECT)\n",
|
|
"c.execute('SELECT * FROM emp')\n",
|
|
"result = c.fetchall()\n",
|
|
"for x in result:\n",
|
|
" print(x[1])\n",
|
|
"c.close()\n",
|
|
" \n",
|
|
" \n",
|
|
"print(\"Der Zugriff über den Spaltennamen ist auch möglich\")\n",
|
|
"conn.row_factory = sqlite3.Row \n",
|
|
"c= conn.cursor()\n",
|
|
"c.execute('SELECT * FROM emp')\n",
|
|
"result = c.fetchall()\n",
|
|
"for x in result:\n",
|
|
" print(x['name'])\n",
|
|
"c.close() \n",
|
|
" "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# fetchone bis None\n",
|
|
"print(\"Für größere Datenmengen sollte man auf fetchall aus performencegründen verzichten. \")\n",
|
|
"c= conn.cursor()\n",
|
|
"c.execute('SELECT * FROM emp')\n",
|
|
"row = c.fetchone()\n",
|
|
"while row != None:\n",
|
|
" print(row['name'])\n",
|
|
" row = c.fetchone()\n",
|
|
"\n",
|
|
"c.close()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Übung: Datensätze einfügen\n",
|
|
"\n",
|
|
"Fügen Sie folgenden Datensatz in die Tabelle emp der Datenbank ein.\n",
|
|
"\n",
|
|
"| ID | Name | Salary | \n",
|
|
"|------|------------|--------|\n",
|
|
"| 10 | May | 4100 | "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#TODO: hier Datensatz einfügen\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"check(conn)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Fehlerbehandlung\n",
|
|
"Bei Datenbankabfragen kann es immer zu Fehlern kommen, diese sollten behandelt werden."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from sqlite3 import OperationalError\n",
|
|
"\n",
|
|
"cur = conn.cursor()\n",
|
|
"try:\n",
|
|
" cur.execute('SELECT * FROM non_existing_emp')\n",
|
|
"except OperationalError as e:\n",
|
|
" print(\"Bei der Datenbankabfrage ist ein Fehler aufgetreten: \" + str(e));\n",
|
|
"cur.close();"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Integration von Python in SQLite\n",
|
|
"\n",
|
|
"Da die Datenbankengine SQLite komplett in Python integriert ist, lassen sich Python-Funktionen direkt in SQL nutzen. \n",
|
|
"Um eine normale Single-Row-Funktion zu Verwenden muss man diese in der Verbindung mit `create_function` registieren.\n",
|
|
"Dieser Mechanismus funktioniert auch mit Multi-Row-Funktionen. Eine Multi-Row-Funktion wird in Python durch eine Klasse abgebildet. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#\n",
|
|
"# Single Row Function\n",
|
|
"#\n",
|
|
"def format_ename(t):\n",
|
|
" return \"Emp Name: \" + t \n",
|
|
"\n",
|
|
"\n",
|
|
"conn.create_function(\"format_ename\", 1, format_ename)\n",
|
|
"cur = conn.cursor()\n",
|
|
"cur.execute(\"select format_ename(e.name) from emp e\")\n",
|
|
"# Zum Testen der Funktion wird nur der Wert ausgegeben\n",
|
|
"print(cur.fetchone()[0])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#\n",
|
|
"# Das funktioniert auch mit Aggregatsfunktionen\n",
|
|
"#\n",
|
|
"class SqrSum:\n",
|
|
" def __init__(self):\n",
|
|
" self.count = 0\n",
|
|
"\n",
|
|
" def step(self, value):\n",
|
|
" self.count += value*value\n",
|
|
"\n",
|
|
" def finalize(self):\n",
|
|
" return self.count\n",
|
|
"\n",
|
|
"conn.create_aggregate(\"sqr_sum\", 1, SqrSum)\n",
|
|
"cur = conn.cursor()\n",
|
|
"cur.execute(\"select sqr_sum(sal) from emp\")\n",
|
|
"print(\"Die quadartische Summe der Gehälter ist \" + str(cur.fetchone()[0]))"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.8.0"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|