├── LICENSE ├── README.md ├── img ├── 01.jpg ├── 02.jpg ├── ERD.png ├── ERD2.png └── logo.png └── mysql.ipynb /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Craig 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CraigDoesData][logo]][link] 2 | 3 | [logo]: ./img/logo.png 4 | [link]: https://www.craigdoesdata.com/ 5 | 6 | 7 | # MySQL + Python for Data Analysts 8 | 9 | Using [MySQL Connector](https://dev.mysql.com/doc/connector-python/en/) and Python to implement a database on MySQL Server, and to create, read, update and delete data in that database. 10 | 11 | #### Project status - Complete 12 | 13 | 14 | ## Introduction 15 | 16 | This repo accompanies [this tutorial]() I wrote for [freeCodeCamp](https://www.freecodecamp.org/). 17 | 18 | The [notebook](https://github.com/thecraigd/Python_SQL/blob/master/mysql.ipynb) takes the reader step-by-step through all the processes involved with using Python and the [MySQL Connector](https://dev.mysql.com/doc/connector-python/en/) to perform the standard [CRUD functions](https://stackify.com/what-are-crud-operations/) on a database running on [MySQL Server](https://dev.mysql.com/downloads/mysql/). 19 | 20 | This repository uses code and data from [this repository](https://github.com/thecraigd/SQL_School_Tutorial/) which accompanies my [series of SQL Tutorials](https://towardsdatascience.com/tagged/sql-series) on [Towards Data Science](https://towardsdatascience.com/). If you are not familiar with relational databases and SQL, I recommend going through those tutorials first. 21 | 22 | We will be implementing the same code to build the below database for the International Language School, but this time doing it via Python using MySQL Connector. 23 | 24 | 25 | [![Entity Relationship Diagram for Database][erd]][link1] 26 | 27 | [erd]: ./img/ERD.png 28 | [link1]: https://towardsdatascience.com/designing-a-relational-database-and-creating-an-entity-relationship-diagram-89c1c19320b2 29 | 30 | ----------------- 31 | 32 | 33 | ### Methods used 34 | * Defining functions in Python 35 | * Database Implementation 36 | * Creating, Reading, Updating and Deleting data using SQL and Python 37 | 38 | 39 | ### Technologies used 40 | * [MySQL Community Server](https://dev.mysql.com/downloads/mysql/) 41 | * [MySQL Python Connector](https://dev.mysql.com/doc/connector-python/en/) 42 | * [PopSQL](https://popsql.com/) 43 | * [Jupyter Notebook](https://jupyter.org/) 44 | * [pandas](https://pandas.pydata.org/) 45 | 46 | ### Data sources 47 | The data used were created by myself for an earlier [project](https://github.com/thecraigd/SQL_School_Tutorial). 48 | Some participant names were created using [Fake Name Generator](https://www.fakenamegenerator.com/). 49 | 50 | 51 | ### Getting started 52 | 53 | 1. Clone this repo (for help see this [tutorial](https://help.github.com/articles/cloning-a-repository/)). 54 | 2. All code is contained within the [Jupyter Notebook](https://github.com/thecraigd/Python_SQL/blob/master/mysql.ipynb) for this project, stored in the root folder as mysql.ipynb 55 | 56 | 57 | ## Featured Notebooks 58 | * [mysql](https://github.com/thecraigd/Python_SQL/blob/master/mysql.ipynb) 59 | 60 | * [](https://mybinder.org/v2/gh/thecraigd/Python_SQL/master) 61 | 62 | ## Contact 63 | All feedback is warmly received. Craig Dickson can be contacted at [craigdoesdata.com](https://www.craigdoesdata.com/contact.html). 64 | -------------------------------------------------------------------------------- /img/01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thecraigd/Python_SQL/4821dc0d477ecac8bd4bb01017406ae4513e9cf5/img/01.jpg -------------------------------------------------------------------------------- /img/02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thecraigd/Python_SQL/4821dc0d477ecac8bd4bb01017406ae4513e9cf5/img/02.jpg -------------------------------------------------------------------------------- /img/ERD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thecraigd/Python_SQL/4821dc0d477ecac8bd4bb01017406ae4513e9cf5/img/ERD.png -------------------------------------------------------------------------------- /img/ERD2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thecraigd/Python_SQL/4821dc0d477ecac8bd4bb01017406ae4513e9cf5/img/ERD2.png -------------------------------------------------------------------------------- /img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thecraigd/Python_SQL/4821dc0d477ecac8bd4bb01017406ae4513e9cf5/img/logo.png -------------------------------------------------------------------------------- /mysql.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "[![CraigDoesData][logo]][link]\n", 8 | "\n", 9 | "[logo]: ./img/logo.png\n", 10 | "[link]: https://www.craigdoesdata.de/\n", 11 | "\n", 12 | "\n", 13 | "# MySQL + Python for Data Analysts\n", 14 | "\n", 15 | "Using [MySQL Connector](https://dev.mysql.com/doc/connector-python/en/) and Python to implement a database on MySQL Server, and to create, read, update and delete data in that database.\n", 16 | "\n", 17 | "#### Project status - Complete\n", 18 | "\n", 19 | "\n", 20 | "## Introduction\n", 21 | "\n", 22 | "This notebook accompanies [this tutorial]() I wrote for [freeCodeCamp](https://www.freecodecamp.org/).\n", 23 | "\n", 24 | "The notebook takes the reader step-by-step through all the processes involved with using Python and the [MySQL Connector](https://dev.mysql.com/doc/connector-python/en/) to perform the standard [CRUD functions](https://stackify.com/what-are-crud-operations/) on a database running on [MySQL Server](https://dev.mysql.com/downloads/mysql/).\n", 25 | "\n", 26 | "This notebook uses code and data from [this repository](https://github.com/thecraigd/SQL_School_Tutorial/) which accompanies my [series of SQL Tutorials](https://towardsdatascience.com/tagged/sql-series) on [Towards Data Science](https://towardsdatascience.com/). If you are not familiar with relational databases and SQL, I recommend going through those tutorials first.\n", 27 | "\n", 28 | "We will be implementing the same code to build the below database for the International Language School, but this time doing it via Python using MySQL Connector.\n", 29 | "\n", 30 | "\n", 31 | "[![Entity Relationship Diagram for Database][erd]][link1]\n", 32 | "\n", 33 | "[erd]: ./img/ERD.png\n", 34 | "[link1]: https://towardsdatascience.com/designing-a-relational-database-and-creating-an-entity-relationship-diagram-89c1c19320b2\n", 35 | "\n", 36 | "-----------------\n", 37 | "\n", 38 | "\n", 39 | "### Methods used\n", 40 | "* Defining functions in Python\n", 41 | "* Database Implementation\n", 42 | "* Creating, Reading, Updating and Deleting data using SQL and Python\n", 43 | "\n", 44 | "\n", 45 | "### Technologies used\n", 46 | "* [MySQL Community Server](https://dev.mysql.com/downloads/mysql/)\n", 47 | "* [MySQL Python Connector](https://dev.mysql.com/doc/connector-python/en/)\n", 48 | "* [PopSQL](https://popsql.com/)\n", 49 | "* [Jupyter Notebook](https://jupyter.org/)\n", 50 | "* [pandas](https://pandas.pydata.org/)\n", 51 | "\n", 52 | "### Data sources\n", 53 | "The data used were created by myself for an earlier [project](https://github.com/thecraigd/SQL_School_Tutorial). \n", 54 | "Some participant names were created using [Fake Name Generator](https://www.fakenamegenerator.com/).\n", 55 | "\n", 56 | "\n", 57 | "\n", 58 | "---------------------\n", 59 | "\n", 60 | "\n", 61 | "## Table of Contents\n", 62 | "\n", 63 | "#### 1. Library Import\n", 64 | "* 1.1 Library Import\n", 65 | "\n", 66 | "#### 2. Connect to Server and Create Database\n", 67 | "* 2.1 Define Server Connection Function \n", 68 | "* 2.2 Create a New Database\n", 69 | "* 2.3 Modify Server Connection Function, Create Database Connection Function\n", 70 | "* 2.4 Define Query Execution Function\n", 71 | "\n", 72 | "#### 3. Creating Tables\n", 73 | "* 3.1 Create Teacher Table\n", 74 | "* 3.2 Create Remaining Tables\n", 75 | "* 3.3 Define Foreign Key Relationships\n", 76 | "\n", 77 | "#### 4. Populating Tables\n", 78 | "* 4.1 Populate Teacher Table\n", 79 | "* 4.2 Populate Remaining Tables\n", 80 | "\n", 81 | "#### 5. Reading Data\n", 82 | "* 5.1 Define Data Reading Function\n", 83 | "* 5.2 - Read Data from Database\n", 84 | "* 5.3 - Formatting Output into a List\n", 85 | "* 5.4 - Formatting Output into a List of Lists\n", 86 | "* 5.5 - Formatting Output into a pandas DataFrame\n", 87 | "\n", 88 | "#### 6. Updating Records\n", 89 | "* 6.1 Updating Client Address\n", 90 | "\n", 91 | "#### 7. Deleting Records\n", 92 | "* 7.1 Deleting a Course\n", 93 | "* 7.2 Restoring the Course\n", 94 | "\n", 95 | "#### 8. Creating Records from Lists\n", 96 | "* 8.1 Create Execute List Query Function\n", 97 | "* 8.2 Add New Teachers\n", 98 | "\n", 99 | "#### 9. Conclusion\n", 100 | "* 9.1 Conclusion\n", 101 | "\n", 102 | "--------------\n", 103 | "\n", 104 | "### 1. Import Libraries\n", 105 | "\n", 106 | "##### 1.1 - Import Libraries\n", 107 | "\n", 108 | "Our first step is to import [MySQL Connector](https://dev.mysql.com/doc/connector-python/en/) and [pandas](https://pandas.pydata.org/)." 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 1, 114 | "metadata": {}, 115 | "outputs": [], 116 | "source": [ 117 | "import mysql.connector\n", 118 | "from mysql.connector import Error\n", 119 | "import pandas as pd" 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": {}, 125 | "source": [ 126 | "-------------------\n", 127 | "\n", 128 | "### 2. Connect to Server and Create Database\n", 129 | "\n", 130 | "##### 2.1 - Define Server Connection Function \n", 131 | "\n", 132 | "Next we want to define a function in python which connects to our MySQL Server (for info on how to set this up, see [my previous article](https://towardsdatascience.com/coding-and-implementing-a-relational-database-using-mysql-d9bc69be90f5). To do this we use the [mysql.connector.connect()](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysql-connector-connect.html) method.\n", 133 | "\n", 134 | "**N.B. Update the variable 'pw' with the root password for your MySQL Server! Otherwise the connection cannot be made.**" 135 | ] 136 | }, 137 | { 138 | "cell_type": "code", 139 | "execution_count": 2, 140 | "metadata": {}, 141 | "outputs": [ 142 | { 143 | "name": "stdout", 144 | "output_type": "stream", 145 | "text": [ 146 | "MySQL Database connection successful\n" 147 | ] 148 | } 149 | ], 150 | "source": [ 151 | "def create_server_connection(host_name, user_name, user_password):\n", 152 | " connection = None\n", 153 | " try:\n", 154 | " connection = mysql.connector.connect(\n", 155 | " host=host_name,\n", 156 | " user=user_name,\n", 157 | " passwd=user_password\n", 158 | " )\n", 159 | " print(\"MySQL Database connection successful\")\n", 160 | " except Error as err:\n", 161 | " print(f\"Error: '{err}'\")\n", 162 | "\n", 163 | " return connection\n", 164 | "\n", 165 | "pw = \"******\" # IMPORTANT! Put your MySQL Terminal password here.\n", 166 | "db = \"school\" # This is the name of the database we will create in the next step - call it whatever you like.\n", 167 | "\n", 168 | "connection = create_server_connection(\"localhost\", \"root\", pw)" 169 | ] 170 | }, 171 | { 172 | "cell_type": "markdown", 173 | "metadata": {}, 174 | "source": [ 175 | "##### 2.2 - Create a New Database\n", 176 | "\n", 177 | "Now we define a function to create a new database on our server. Here we are using [cursor.execute()](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html) to execute a [CREATE DATABASE](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) SQL command." 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": 3, 183 | "metadata": {}, 184 | "outputs": [ 185 | { 186 | "name": "stdout", 187 | "output_type": "stream", 188 | "text": [ 189 | "Database created successfully\n" 190 | ] 191 | } 192 | ], 193 | "source": [ 194 | "def create_database(connection, query):\n", 195 | " cursor = connection.cursor()\n", 196 | " try:\n", 197 | " cursor.execute(query)\n", 198 | " print(\"Database created successfully\")\n", 199 | " except Error as err:\n", 200 | " print(f\"Error: '{err}'\")\n", 201 | "\n", 202 | "create_database_query = \"CREATE DATABASE school\"\n", 203 | "create_database(connection, create_database_query)" 204 | ] 205 | }, 206 | { 207 | "cell_type": "markdown", 208 | "metadata": {}, 209 | "source": [ 210 | "##### 2.3 - Modify Server Connection Function, Create Database Connection Function\n", 211 | "\n", 212 | "Now that we've created a DB, let's modify our create_server_connection function to create a new function for connecting directly to that DB. This will prove more useful than just connecting to our server." 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": 4, 218 | "metadata": {}, 219 | "outputs": [], 220 | "source": [ 221 | "def create_db_connection(host_name, user_name, user_password, db_name):\n", 222 | " connection = None\n", 223 | " try:\n", 224 | " connection = mysql.connector.connect(\n", 225 | " host=host_name,\n", 226 | " user=user_name,\n", 227 | " passwd=user_password,\n", 228 | " database=db_name\n", 229 | " )\n", 230 | " print(\"MySQL Database connection successful\")\n", 231 | " except Error as err:\n", 232 | " print(f\"Error: '{err}'\")\n", 233 | "\n", 234 | " return connection" 235 | ] 236 | }, 237 | { 238 | "cell_type": "markdown", 239 | "metadata": {}, 240 | "source": [ 241 | "##### 2.4 - Define Query Execution Function\n", 242 | "\n", 243 | "The final step of this stage is to create a function which will allow us to execute queries written in SQL. This is going to be extremely useful!\n", 244 | "\n", 245 | "Again, we use [cursor.execute()](https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html) to execute our commands." 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": 5, 251 | "metadata": {}, 252 | "outputs": [], 253 | "source": [ 254 | "def execute_query(connection, query):\n", 255 | " cursor = connection.cursor()\n", 256 | " try:\n", 257 | " cursor.execute(query)\n", 258 | " connection.commit()\n", 259 | " print(\"Query successful\")\n", 260 | " except Error as err:\n", 261 | " print(f\"Error: '{err}'\")" 262 | ] 263 | }, 264 | { 265 | "cell_type": "markdown", 266 | "metadata": {}, 267 | "source": [ 268 | "-------------------\n", 269 | "\n", 270 | "### 3. Creating Tables\n", 271 | "\n", 272 | "##### 3.1 - Create Teacher Table\n", 273 | "\n", 274 | "Now let's create our first table inside our DB, using our newly defined functions." 275 | ] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "execution_count": 6, 280 | "metadata": {}, 281 | "outputs": [ 282 | { 283 | "name": "stdout", 284 | "output_type": "stream", 285 | "text": [ 286 | "MySQL Database connection successful\n", 287 | "Query successful\n" 288 | ] 289 | } 290 | ], 291 | "source": [ 292 | "# Assign our SQL command to a python variable using triple quotes to create a multi-line string\n", 293 | "create_teacher_table = \"\"\"\n", 294 | "CREATE TABLE teacher (\n", 295 | " teacher_id INT PRIMARY KEY,\n", 296 | " first_name VARCHAR(40) NOT NULL,\n", 297 | " last_name VARCHAR(40) NOT NULL,\n", 298 | " language_1 VARCHAR(3) NOT NULL,\n", 299 | " language_2 VARCHAR(3),\n", 300 | " dob DATE,\n", 301 | " tax_id INT UNIQUE,\n", 302 | " phone_no VARCHAR(20)\n", 303 | " );\n", 304 | " \"\"\"\n", 305 | "\n", 306 | "connection = create_db_connection(\"localhost\", \"root\", pw, db) # Connect to the Database\n", 307 | "execute_query(connection, create_teacher_table) # Execute our defined query" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "If we check in our MySQL terminal using SHOW TABLES; we see the following:\n", 315 | "\n", 316 | "\n", 317 | "\n", 318 | "Success! The teacher table has been created.\n", 319 | "\n", 320 | "##### 3.2 - Create Remaining Tables\n", 321 | "\n", 322 | "Now let's create the rest of our tables." 323 | ] 324 | }, 325 | { 326 | "cell_type": "code", 327 | "execution_count": 7, 328 | "metadata": {}, 329 | "outputs": [ 330 | { 331 | "name": "stdout", 332 | "output_type": "stream", 333 | "text": [ 334 | "MySQL Database connection successful\n", 335 | "Query successful\n", 336 | "Query successful\n", 337 | "Query successful\n" 338 | ] 339 | } 340 | ], 341 | "source": [ 342 | "create_client_table = \"\"\"\n", 343 | "CREATE TABLE client (\n", 344 | " client_id INT PRIMARY KEY,\n", 345 | " client_name VARCHAR(40) NOT NULL,\n", 346 | " address VARCHAR(60) NOT NULL,\n", 347 | " industry VARCHAR(20)\n", 348 | ");\n", 349 | " \"\"\"\n", 350 | "\n", 351 | "create_participant_table = \"\"\"\n", 352 | "CREATE TABLE participant (\n", 353 | " participant_id INT PRIMARY KEY,\n", 354 | " first_name VARCHAR(40) NOT NULL,\n", 355 | " last_name VARCHAR(40) NOT NULL,\n", 356 | " phone_no VARCHAR(20),\n", 357 | " client INT\n", 358 | ");\n", 359 | "\"\"\"\n", 360 | "\n", 361 | "create_course_table = \"\"\"\n", 362 | "CREATE TABLE course (\n", 363 | " course_id INT PRIMARY KEY,\n", 364 | " course_name VARCHAR(40) NOT NULL,\n", 365 | " language VARCHAR(3) NOT NULL,\n", 366 | " level VARCHAR(2),\n", 367 | " course_length_weeks INT,\n", 368 | " start_date DATE,\n", 369 | " in_school BOOLEAN,\n", 370 | " teacher INT,\n", 371 | " client INT\n", 372 | ");\n", 373 | "\"\"\"\n", 374 | "\n", 375 | "\n", 376 | "connection = create_db_connection(\"localhost\", \"root\", pw, db)\n", 377 | "execute_query(connection, create_client_table)\n", 378 | "execute_query(connection, create_participant_table)\n", 379 | "execute_query(connection, create_course_table)" 380 | ] 381 | }, 382 | { 383 | "cell_type": "markdown", 384 | "metadata": {}, 385 | "source": [ 386 | "##### 3.3 - Define Foreign Key Relationships\n", 387 | "\n", 388 | "Now altering the tables to create Foreign Key relationships (see the accompanying [SQL Tutorial Series](https://towardsdatascience.com/tagged/sql-series) on [Towards Data Science](https://towardsdatascience.com/) for the background on all of this), and creating our final table, takes_course" 389 | ] 390 | }, 391 | { 392 | "cell_type": "code", 393 | "execution_count": 8, 394 | "metadata": {}, 395 | "outputs": [ 396 | { 397 | "name": "stdout", 398 | "output_type": "stream", 399 | "text": [ 400 | "MySQL Database connection successful\n", 401 | "Query successful\n", 402 | "Query successful\n", 403 | "Query successful\n", 404 | "Query successful\n" 405 | ] 406 | } 407 | ], 408 | "source": [ 409 | "alter_participant = \"\"\"\n", 410 | "ALTER TABLE participant\n", 411 | "ADD FOREIGN KEY(client)\n", 412 | "REFERENCES client(client_id)\n", 413 | "ON DELETE SET NULL;\n", 414 | "\"\"\"\n", 415 | "\n", 416 | "alter_course = \"\"\"\n", 417 | "ALTER TABLE course\n", 418 | "ADD FOREIGN KEY(teacher)\n", 419 | "REFERENCES teacher(teacher_id)\n", 420 | "ON DELETE SET NULL;\n", 421 | "\"\"\"\n", 422 | "\n", 423 | "alter_course_again = \"\"\"\n", 424 | "ALTER TABLE course\n", 425 | "ADD FOREIGN KEY(client)\n", 426 | "REFERENCES client(client_id)\n", 427 | "ON DELETE SET NULL;\n", 428 | "\"\"\"\n", 429 | "\n", 430 | "create_takescourse_table = \"\"\"\n", 431 | "CREATE TABLE takes_course (\n", 432 | " participant_id INT,\n", 433 | " course_id INT,\n", 434 | " PRIMARY KEY(participant_id, course_id),\n", 435 | " FOREIGN KEY(participant_id) REFERENCES participant(participant_id) ON DELETE CASCADE, -- it makes no sense to keep this rtelation when a participant or course is no longer in the system, hence why CASCADE this time\n", 436 | " FOREIGN KEY(course_id) REFERENCES course(course_id) ON DELETE CASCADE\n", 437 | ");\n", 438 | "\"\"\"\n", 439 | "\n", 440 | "connection = create_db_connection(\"localhost\", \"root\", pw, db)\n", 441 | "execute_query(connection, alter_participant)\n", 442 | "execute_query(connection, alter_course)\n", 443 | "execute_query(connection, alter_course_again)\n", 444 | "execute_query(connection, create_takescourse_table)\n" 445 | ] 446 | }, 447 | { 448 | "cell_type": "markdown", 449 | "metadata": {}, 450 | "source": [ 451 | "-----------------\n", 452 | "\n", 453 | "### 4. Populate Tables\n", 454 | "\n", 455 | "The next step is to populate our tables with data, starting with the teacher table\n", 456 | "\n", 457 | "##### 4.1 - Populate Teacher Table\n", 458 | "\n", 459 | "Here we again assign a multi-line string with our SQL command to a variable, and then call our create_db_connection and execute_query functions." 460 | ] 461 | }, 462 | { 463 | "cell_type": "code", 464 | "execution_count": 9, 465 | "metadata": {}, 466 | "outputs": [ 467 | { 468 | "name": "stdout", 469 | "output_type": "stream", 470 | "text": [ 471 | "MySQL Database connection successful\n", 472 | "Query successful\n" 473 | ] 474 | } 475 | ], 476 | "source": [ 477 | "pop_teacher = \"\"\"\n", 478 | "INSERT INTO teacher VALUES\n", 479 | "(1, 'James', 'Smith', 'ENG', NULL, '1985-04-20', 12345, '+491774553676'),\n", 480 | "(2, 'Stefanie', 'Martin', 'FRA', NULL, '1970-02-17', 23456, '+491234567890'), \n", 481 | "(3, 'Steve', 'Wang', 'MAN', 'ENG', '1990-11-12', 34567, '+447840921333'),\n", 482 | "(4, 'Friederike', 'Müller-Rossi', 'DEU', 'ITA', '1987-07-07', 45678, '+492345678901'),\n", 483 | "(5, 'Isobel', 'Ivanova', 'RUS', 'ENG', '1963-05-30', 56789, '+491772635467'),\n", 484 | "(6, 'Niamh', 'Murphy', 'ENG', 'IRI', '1995-09-08', 67890, '+491231231232');\n", 485 | "\"\"\"\n", 486 | "\n", 487 | "connection = create_db_connection(\"localhost\", \"root\", pw, db)\n", 488 | "execute_query(connection, pop_teacher)" 489 | ] 490 | }, 491 | { 492 | "cell_type": "markdown", 493 | "metadata": {}, 494 | "source": [ 495 | "Let's take a look in MySQL terminal:\n", 496 | "\n", 497 | "\n", 498 | "\n", 499 | "Success! We can see the table has been properly filled with all of our data.\n", 500 | "\n", 501 | "##### 4.2 - Populate Remaining Tables\n", 502 | "\n", 503 | "Now, let's populate the remaining tables." 504 | ] 505 | }, 506 | { 507 | "cell_type": "code", 508 | "execution_count": 10, 509 | "metadata": {}, 510 | "outputs": [ 511 | { 512 | "name": "stdout", 513 | "output_type": "stream", 514 | "text": [ 515 | "MySQL Database connection successful\n", 516 | "Query successful\n", 517 | "Query successful\n", 518 | "Query successful\n", 519 | "Query successful\n" 520 | ] 521 | } 522 | ], 523 | "source": [ 524 | "pop_client = \"\"\"\n", 525 | "INSERT INTO client VALUES\n", 526 | "(101, 'Big Business Federation', '123 Falschungstraße, 10999 Berlin', 'NGO'),\n", 527 | "(102, 'eCommerce GmbH', '27 Ersatz Allee, 10317 Berlin', 'Retail'),\n", 528 | "(103, 'AutoMaker AG', '20 Künstlichstraße, 10023 Berlin', 'Auto'),\n", 529 | "(104, 'Banko Bank', '12 Betrugstraße, 12345 Berlin', 'Banking'),\n", 530 | "(105, 'WeMoveIt GmbH', '138 Arglistweg, 10065 Berlin', 'Logistics');\n", 531 | "\"\"\"\n", 532 | "\n", 533 | "pop_participant = \"\"\"\n", 534 | "INSERT INTO participant VALUES\n", 535 | "(101, 'Marina', 'Berg','491635558182', 101),\n", 536 | "(102, 'Andrea', 'Duerr', '49159555740', 101),\n", 537 | "(103, 'Philipp', 'Probst', '49155555692', 102),\n", 538 | "(104, 'René', 'Brandt', '4916355546', 102),\n", 539 | "(105, 'Susanne', 'Shuster', '49155555779', 102),\n", 540 | "(106, 'Christian', 'Schreiner', '49162555375', 101),\n", 541 | "(107, 'Harry', 'Kim', '49177555633', 101),\n", 542 | "(108, 'Jan', 'Nowak', '49151555824', 101),\n", 543 | "(109, 'Pablo', 'Garcia', '49162555176', 101),\n", 544 | "(110, 'Melanie', 'Dreschler', '49151555527', 103),\n", 545 | "(111, 'Dieter', 'Durr', '49178555311', 103),\n", 546 | "(112, 'Max', 'Mustermann', '49152555195', 104),\n", 547 | "(113, 'Maxine', 'Mustermann', '49177555355', 104),\n", 548 | "(114, 'Heiko', 'Fleischer', '49155555581', 105);\n", 549 | "\"\"\"\n", 550 | "\n", 551 | "pop_course = \"\"\"\n", 552 | "INSERT INTO course VALUES\n", 553 | "(12, 'English for Logistics', 'ENG', 'A1', 10, '2020-02-01', TRUE, 1, 105),\n", 554 | "(13, 'Beginner English', 'ENG', 'A2', 40, '2019-11-12', FALSE, 6, 101),\n", 555 | "(14, 'Intermediate English', 'ENG', 'B2', 40, '2019-11-12', FALSE, 6, 101),\n", 556 | "(15, 'Advanced English', 'ENG', 'C1', 40, '2019-11-12', FALSE, 6, 101),\n", 557 | "(16, 'Mandarin für Autoindustrie', 'MAN', 'B1', 15, '2020-01-15', TRUE, 3, 103),\n", 558 | "(17, 'Français intermédiaire', 'FRA', 'B1', 18, '2020-04-03', FALSE, 2, 101),\n", 559 | "(18, 'Deutsch für Anfänger', 'DEU', 'A2', 8, '2020-02-14', TRUE, 4, 102),\n", 560 | "(19, 'Intermediate English', 'ENG', 'B2', 10, '2020-03-29', FALSE, 1, 104),\n", 561 | "(20, 'Fortgeschrittenes Russisch', 'RUS', 'C1', 4, '2020-04-08', FALSE, 5, 103);\n", 562 | "\"\"\"\n", 563 | "\n", 564 | "pop_takescourse = \"\"\"\n", 565 | "INSERT INTO takes_course VALUES\n", 566 | "(101, 15),\n", 567 | "(101, 17),\n", 568 | "(102, 17),\n", 569 | "(103, 18),\n", 570 | "(104, 18),\n", 571 | "(105, 18),\n", 572 | "(106, 13),\n", 573 | "(107, 13),\n", 574 | "(108, 13),\n", 575 | "(109, 14),\n", 576 | "(109, 15),\n", 577 | "(110, 16),\n", 578 | "(110, 20),\n", 579 | "(111, 16),\n", 580 | "(114, 12),\n", 581 | "(112, 19),\n", 582 | "(113, 19);\n", 583 | "\"\"\"\n", 584 | "\n", 585 | "connection = create_db_connection(\"localhost\", \"root\", pw, db)\n", 586 | "execute_query(connection, pop_client)\n", 587 | "execute_query(connection, pop_participant)\n", 588 | "execute_query(connection, pop_course)\n", 589 | "execute_query(connection, pop_takescourse)" 590 | ] 591 | }, 592 | { 593 | "cell_type": "markdown", 594 | "metadata": {}, 595 | "source": [ 596 | "--------------\n", 597 | "\n", 598 | "### 5. Reading Data\n", 599 | "\n", 600 | "##### 5.1 - Define Data Reading Function\n", 601 | "\n", 602 | "Now that we have populated our tables, it's time to start creating read queries. To do this, we will need a new function." 603 | ] 604 | }, 605 | { 606 | "cell_type": "code", 607 | "execution_count": 11, 608 | "metadata": {}, 609 | "outputs": [], 610 | "source": [ 611 | "def read_query(connection, query):\n", 612 | " cursor = connection.cursor()\n", 613 | " result = None\n", 614 | " try:\n", 615 | " cursor.execute(query)\n", 616 | " result = cursor.fetchall()\n", 617 | " return result\n", 618 | " except Error as err:\n", 619 | " print(f\"Error: '{err}'\")" 620 | ] 621 | }, 622 | { 623 | "cell_type": "markdown", 624 | "metadata": {}, 625 | "source": [ 626 | "##### 5.2 - Read Data from Database\n", 627 | "\n", 628 | "Let's try this with a simple query to begin with." 629 | ] 630 | }, 631 | { 632 | "cell_type": "code", 633 | "execution_count": 12, 634 | "metadata": {}, 635 | "outputs": [ 636 | { 637 | "name": "stdout", 638 | "output_type": "stream", 639 | "text": [ 640 | "MySQL Database connection successful\n", 641 | "(1, 'James', 'Smith', 'ENG', None, datetime.date(1985, 4, 20), 12345, '+491774553676')\n", 642 | "(2, 'Stefanie', 'Martin', 'FRA', None, datetime.date(1970, 2, 17), 23456, '+491234567890')\n", 643 | "(3, 'Steve', 'Wang', 'MAN', 'ENG', datetime.date(1990, 11, 12), 34567, '+447840921333')\n", 644 | "(4, 'Friederike', 'Müller-Rossi', 'DEU', 'ITA', datetime.date(1987, 7, 7), 45678, '+492345678901')\n", 645 | "(5, 'Isobel', 'Ivanova', 'RUS', 'ENG', datetime.date(1963, 5, 30), 56789, '+491772635467')\n", 646 | "(6, 'Niamh', 'Murphy', 'ENG', 'IRI', datetime.date(1995, 9, 8), 67890, '+491231231232')\n" 647 | ] 648 | } 649 | ], 650 | "source": [ 651 | "q1 = \"\"\"\n", 652 | "SELECT *\n", 653 | "FROM teacher;\n", 654 | "\"\"\"\n", 655 | "\n", 656 | "connection = create_db_connection(\"localhost\", \"root\", pw, db)\n", 657 | "results = read_query(connection, q1)\n", 658 | "\n", 659 | "for result in results:\n", 660 | " print(result)" 661 | ] 662 | }, 663 | { 664 | "cell_type": "markdown", 665 | "metadata": {}, 666 | "source": [ 667 | "And here are some more queries to try." 668 | ] 669 | }, 670 | { 671 | "cell_type": "code", 672 | "execution_count": 13, 673 | "metadata": {}, 674 | "outputs": [ 675 | { 676 | "name": "stdout", 677 | "output_type": "stream", 678 | "text": [ 679 | "MySQL Database connection successful\n", 680 | "(13, 'Beginner English', 'ENG', 'Big Business Federation', '123 Falschungstraße, 10999 Berlin')\n", 681 | "(14, 'Intermediate English', 'ENG', 'Big Business Federation', '123 Falschungstraße, 10999 Berlin')\n", 682 | "(15, 'Advanced English', 'ENG', 'Big Business Federation', '123 Falschungstraße, 10999 Berlin')\n", 683 | "(17, 'Français intermédiaire', 'FRA', 'Big Business Federation', '123 Falschungstraße, 10999 Berlin')\n", 684 | "(19, 'Intermediate English', 'ENG', 'Banko Bank', '12 Betrugstraße, 12345 Berlin')\n", 685 | "(20, 'Fortgeschrittenes Russisch', 'RUS', 'AutoMaker AG', '20 Künstlichstraße, 10023 Berlin')\n" 686 | ] 687 | } 688 | ], 689 | "source": [ 690 | "q2 = \"\"\"\n", 691 | "SELECT last_name, dob\n", 692 | "FROM teacher;\n", 693 | "\"\"\"\n", 694 | "\n", 695 | "q3 = \"\"\"\n", 696 | "SELECT *\n", 697 | "FROM course\n", 698 | "WHERE language = 'ENG'\n", 699 | "ORDER BY start_date DESC;\n", 700 | "\"\"\"\n", 701 | "\n", 702 | "q4 = \"\"\"\n", 703 | "SELECT first_name, last_name, phone_no\n", 704 | "FROM teacher\n", 705 | "WHERE dob < '1990-01-01';\n", 706 | "\"\"\"\n", 707 | "\n", 708 | "q5 = \"\"\"\n", 709 | "SELECT course.course_id, course.course_name, course.language, client.client_name, client.address\n", 710 | "FROM course\n", 711 | "JOIN client\n", 712 | "ON course.client = client.client_id\n", 713 | "WHERE course.in_school = FALSE;\n", 714 | "\"\"\"\n", 715 | "\n", 716 | "connection = create_db_connection(\"localhost\", \"root\", pw, db)\n", 717 | "results = read_query(connection, q5)\n", 718 | "\n", 719 | "for result in results:\n", 720 | " print(result)" 721 | ] 722 | }, 723 | { 724 | "cell_type": "markdown", 725 | "metadata": {}, 726 | "source": [ 727 | "##### 5.3 - Formatting Output into a List\n", 728 | "\n", 729 | "Now we can assign the results to a list, to use further in our python applications or scripts.\n", 730 | "\n", 731 | "The following code returns the results of our query as a list of tuples." 732 | ] 733 | }, 734 | { 735 | "cell_type": "code", 736 | "execution_count": 14, 737 | "metadata": {}, 738 | "outputs": [ 739 | { 740 | "name": "stdout", 741 | "output_type": "stream", 742 | "text": [ 743 | "[(13, 'Beginner English', 'ENG', 'Big Business Federation', '123 Falschungstraße, 10999 Berlin'), (14, 'Intermediate English', 'ENG', 'Big Business Federation', '123 Falschungstraße, 10999 Berlin'), (15, 'Advanced English', 'ENG', 'Big Business Federation', '123 Falschungstraße, 10999 Berlin'), (17, 'Français intermédiaire', 'FRA', 'Big Business Federation', '123 Falschungstraße, 10999 Berlin'), (19, 'Intermediate English', 'ENG', 'Banko Bank', '12 Betrugstraße, 12345 Berlin'), (20, 'Fortgeschrittenes Russisch', 'RUS', 'AutoMaker AG', '20 Künstlichstraße, 10023 Berlin')]\n" 744 | ] 745 | } 746 | ], 747 | "source": [ 748 | "#Initialise empty list\n", 749 | "from_db = []\n", 750 | "\n", 751 | "# Loop over the results and append them into our list, different styles\n", 752 | "\n", 753 | "# Returns a list of tuples\n", 754 | "for result in results:\n", 755 | " result = result\n", 756 | " from_db.append(result)\n", 757 | " \n", 758 | "print(from_db)" 759 | ] 760 | }, 761 | { 762 | "cell_type": "markdown", 763 | "metadata": {}, 764 | "source": [ 765 | "##### 5.4 - Formatting Output into a List of Lists\n", 766 | "\n", 767 | "If we want to, we can make this return a list of lists instead, like so:" 768 | ] 769 | }, 770 | { 771 | "cell_type": "code", 772 | "execution_count": 15, 773 | "metadata": {}, 774 | "outputs": [ 775 | { 776 | "name": "stdout", 777 | "output_type": "stream", 778 | "text": [ 779 | "[[13, 'Beginner English', 'ENG', 'Big Business Federation', '123 Falschungstraße, 10999 Berlin'], [14, 'Intermediate English', 'ENG', 'Big Business Federation', '123 Falschungstraße, 10999 Berlin'], [15, 'Advanced English', 'ENG', 'Big Business Federation', '123 Falschungstraße, 10999 Berlin'], [17, 'Français intermédiaire', 'FRA', 'Big Business Federation', '123 Falschungstraße, 10999 Berlin'], [19, 'Intermediate English', 'ENG', 'Banko Bank', '12 Betrugstraße, 12345 Berlin'], [20, 'Fortgeschrittenes Russisch', 'RUS', 'AutoMaker AG', '20 Künstlichstraße, 10023 Berlin']]\n" 780 | ] 781 | } 782 | ], 783 | "source": [ 784 | "# Returns a list of lists\n", 785 | "from_db = []\n", 786 | "\n", 787 | "for result in results:\n", 788 | " result = list(result)\n", 789 | " from_db.append(result)\n", 790 | " \n", 791 | "print(from_db)" 792 | ] 793 | }, 794 | { 795 | "cell_type": "markdown", 796 | "metadata": {}, 797 | "source": [ 798 | "##### 5.5 - Formatting Output into a pandas [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)\n", 799 | "\n", 800 | "With a little more work (creating a list with our column names), we can create a pandas DataFrame like so:" 801 | ] 802 | }, 803 | { 804 | "cell_type": "code", 805 | "execution_count": 16, 806 | "metadata": {}, 807 | "outputs": [ 808 | { 809 | "data": { 810 | "text/html": [ 811 | "
\n", 829 | " | course_id | \n", 830 | "course_name | \n", 831 | "language | \n", 832 | "client_name | \n", 833 | "address | \n", 834 | "
---|---|---|---|---|---|
0 | \n", 839 | "13 | \n", 840 | "Beginner English | \n", 841 | "ENG | \n", 842 | "Big Business Federation | \n", 843 | "123 Falschungstraße, 10999 Berlin | \n", 844 | "
1 | \n", 847 | "14 | \n", 848 | "Intermediate English | \n", 849 | "ENG | \n", 850 | "Big Business Federation | \n", 851 | "123 Falschungstraße, 10999 Berlin | \n", 852 | "
2 | \n", 855 | "15 | \n", 856 | "Advanced English | \n", 857 | "ENG | \n", 858 | "Big Business Federation | \n", 859 | "123 Falschungstraße, 10999 Berlin | \n", 860 | "
3 | \n", 863 | "17 | \n", 864 | "Français intermédiaire | \n", 865 | "FRA | \n", 866 | "Big Business Federation | \n", 867 | "123 Falschungstraße, 10999 Berlin | \n", 868 | "
4 | \n", 871 | "19 | \n", 872 | "Intermediate English | \n", 873 | "ENG | \n", 874 | "Banko Bank | \n", 875 | "12 Betrugstraße, 12345 Berlin | \n", 876 | "
5 | \n", 879 | "20 | \n", 880 | "Fortgeschrittenes Russisch | \n", 881 | "RUS | \n", 882 | "AutoMaker AG | \n", 883 | "20 Künstlichstraße, 10023 Berlin | \n", 884 | "