Files
obsidian/WS2324/Datenbank/Unterricht/06. Zusatz Datenbankverbindung mit Python/Lernmodul Datenbankzugriff in Python.ipynb

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
}