sql >> Database teknologi >  >> RDS >> Mysql

Python og MySQL Database:En praktisk introduktion

MySQL er et af de mest populære databasestyringssystemer (DBMS'er) på markedet i dag. Det var kun nummer to efter Oracle DBMS i dette års DB-Engines Ranking. Da de fleste softwareapplikationer skal interagere med data i en eller anden form, giver programmeringssprog som Python værktøjer til lagring og adgang til disse datakilder.

Ved at bruge de teknikker, der er diskuteret i denne tutorial, vil du være i stand til effektivt at integrere en MySQL-database med en Python-applikation. Du vil udvikle en lille MySQL-database til et filmvurderingssystem og lære, hvordan du forespørger direkte fra din Python-kode.

I slutningen af ​​dette selvstudie vil du være i stand til:

  • Identificer unikke funktioner i MySQL
  • Tilslut din applikation til en MySQL-database
  • Forespørg databasen for at hente nødvendige data
  • Håndter undtagelser der opstår under adgang til databasen
  • Brug bedste fremgangsmåder mens du bygger databaseapplikationer

For at få mest muligt ud af denne øvelse, bør du have et praktisk kendskab til Python-koncepter som for loops, funktioner, undtagelseshåndtering og installation af Python-pakker ved hjælp af pip . Du bør også have en grundlæggende forståelse af relationelle databasestyringssystemer og SQL-forespørgsler som SELECT , DROP , CREATE , og JOIN .

Gratis download: Få et eksempelkapitel fra Python Tricks:The Book, der viser dig Pythons bedste praksis med enkle eksempler, som du kan anvende med det samme for at skrive smukkere + Pythonic kode.


Sammenligning af MySQL med andre SQL-databaser

SQL står for Structured Query Language og er et meget brugt programmeringssprog til styring af relationelle databaser. Du har måske hørt om de forskellige varianter af SQL-baserede DBMS'er. De mest populære inkluderer MySQL, PostgreSQL, SQLite og SQL Server. Alle disse databaser er kompatible med SQL-standarderne, men med varierende grad af overholdelse.

At være open source siden starten i 1995 blev MySQL hurtigt markedsleder blandt SQL-løsninger. MySQL er også en del af Oracle-økosystemet. Mens dens kernefunktionalitet er helt gratis, er der også nogle betalte tilføjelser. I øjeblikket bruges MySQL af alle større teknologivirksomheder, inklusive Google, LinkedIn, Uber, Netflix, Twitter og andre.

Bortset fra et stort open source-fællesskab til support, er der mange andre grunde til MySQL's succes:

  1. Nem installation: MySQL er designet til at være brugervenligt. Det er ret ligetil at opsætte en MySQL-database, og adskillige bredt tilgængelige tredjepartsværktøjer, såsom phpMyAdmin, strømliner yderligere opsætningsprocessen. MySQL er tilgængelig til alle større operativsystemer, inklusive Windows, macOS, Linux og Solaris.

  2. Hastighed: MySQL har ry for at være en overordentlig hurtig databaseløsning. Den har et relativt mindre fodaftryk og er ekstremt skalerbar i det lange løb.

  3. Brugerrettigheder og sikkerhed: MySQL kommer med et script, der giver dig mulighed for at indstille adgangskodesikkerhedsniveauet, tildele administratoradgangskoder og tilføje og fjerne brugerkontorettigheder. Dette script ukomplicerer administrationsprocessen for en webhostingbrugeradministrationsportal. Andre DBMS'er, som PostgreSQL, bruger konfigurationsfiler, der er mere komplicerede at bruge.

Mens MySQL er berømt for sin hastighed og brugervenlighed, kan du få mere avancerede funktioner med PostgreSQL. Desuden er MySQL ikke fuldt SQL-kompatibel og har visse funktionelle begrænsninger, såsom ingen understøttelse af FULL JOIN klausuler.

Du kan også støde på nogle problemer med samtidig læsning og skrivning i MySQL. Hvis din software har mange brugere, der skriver data til den på én gang, så er PostgreSQL måske et mere passende valg.

Bemærk: For en mere dybdegående sammenligning af MySQL og PostgreSQL i en virkelig verden, se Hvorfor Uber Engineering skiftede fra Postgres til MySQL.

SQL Server er også en meget populær DBMS og er kendt for sin pålidelighed, effektivitet og sikkerhed. Det foretrækkes af virksomheder, især i bankdomænet, som regelmæssigt håndterer store trafikbelastninger. Det er en kommerciel løsning og er et af de systemer, der er mest kompatible med Windows-tjenester.

I 2010, da Oracle købte Sun Microsystems og MySQL, var mange bekymrede for MySQL's fremtid. På det tidspunkt var Oracle MySQL’s største konkurrent. Udviklere frygtede, at dette var en fjendtlig overtagelse fra Oracle med det formål at ødelægge MySQL.

Adskillige udviklere ledet af Michael Widenius, den oprindelige forfatter af MySQL, skabte en forgrening af MySQL-kodebasen og lagde grundlaget for MariaDB. Målet var at sikre adgang til MySQL og holde den fri for evigt.

Til dato forbliver MariaDB fuldt GPL-licenseret, og holder det fuldstændigt i det offentlige domæne. Nogle funktioner i MySQL er på den anden side kun tilgængelige med betalte licenser. MariaDB tilbyder også flere ekstremt nyttige funktioner, der ikke understøttes af MySQL-serveren, såsom distribueret SQL og kolonneopbevaring. Du kan finde flere forskelle mellem MySQL og MariaDB opført på MariaDBs hjemmeside.

MySQL bruger en meget lignende syntaks til Standard SQL. Der er dog nogle bemærkelsesværdige forskelle nævnt i den officielle dokumentation.



Installation af MySQL Server og MySQL Connector/Python

Nu, for at begynde at arbejde gennem denne vejledning, skal du konfigurere to ting:en MySQL-server og et MySQL-stik . MySQL-serveren vil levere alle de tjenester, der kræves til at håndtere din database. Når serveren er oppe og køre, kan du forbinde din Python-applikation med den ved hjælp af MySQL Connector/Python.


Installation af MySQL Server

Den officielle dokumentation beskriver den anbefalede måde at downloade og installere MySQL-server på. Du finder instruktioner til alle populære operativsystemer, inklusive Windows, macOS, Solaris, Linux og mange flere.

For Windows er den bedste måde at downloade MySQL Installer og lade det tage sig af hele processen. Installationsmanageren hjælper dig også med at konfigurere sikkerhedsindstillingerne for MySQL-serveren. På siden Konti og roller skal du indtaste en adgangskode til roden (admin) konto og også eventuelt tilføje andre brugere med forskellige privilegier:

Selvom du skal angive legitimationsoplysninger for root-kontoen under opsætningen, kan du ændre disse indstillinger senere.

Bemærk: Husk værtsnavnet, brugernavnet og adgangskoden, da disse vil være nødvendige for at oprette forbindelse til MySQL-serveren senere.

Selvom du kun har brug for MySQL-serveren til denne vejledning, kan du også konfigurere andre nyttige værktøjer som MySQL Workbench ved hjælp af disse installationsprogrammer. Hvis du ikke vil installere MySQL direkte i dit operativsystem, så er implementering af MySQL på Linux med Docker et praktisk alternativ.



Installation af MySQL Connector/Python

En databasedriver er et stykke software, der tillader et program at forbinde og interagere med et databasesystem. Programmeringssprog som Python har brug for en speciel driver, før de kan tale til en database fra en bestemt leverandør.

Disse drivere fås typisk som tredjepartsmoduler. Python Database API (DB-API) definerer den standardgrænseflade, som alle Python-databasedrivere skal overholde. Disse detaljer er dokumenteret i PEP 249. Alle Python-databasedrivere, såsom sqlite3 til SQLite, psycopg for PostgreSQL og MySQL Connector/Python til MySQL, følger disse implementeringsregler.

Bemærk: MySQLs officielle dokumentation bruger udtrykket connector i stedet for chauffør . Teknisk set er connectors kun forbundet med at oprette forbindelse til en database, ikke at interagere med den. Imidlertid bruges udtrykket ofte for hele databaseadgangsmodulet, der omfatter forbindelsen og chaufføren.

For at bevare overensstemmelse med dokumentationen kan du se udtrykket forbindelse hver gang MySQL er nævnt.

Mange populære programmeringssprog har deres egen database API. For eksempel har Java Java Database Connectivity (JDBC) API. Hvis du skal forbinde en Java-applikation til en MySQL-database, skal du bruge MySQL JDBC-forbindelsen, som følger JDBC API.

Tilsvarende skal du i Python installere en Python MySQL-connector for at interagere med en MySQL-database. Mange pakker følger DB-API-standarderne, men den mest populære blandt dem er MySQL Connector/Python. Du kan få det med pip :

$ pip install mysql-connector-python

pip installerer stikket som et tredjepartsmodul i det aktuelt aktive virtuelle miljø. Det anbefales, at du opsætter et isoleret virtuelt miljø for projektet sammen med alle afhængigheder.

For at teste, om installationen lykkedes, skal du skrive følgende kommando på din Python-terminal:

>>>
>>> import mysql.connector

Hvis ovenstående kode udføres uden fejl, så mysql.connector er installeret og klar til brug. Hvis du støder på fejl, så sørg for, at du er i det rigtige virtuelle miljø, og at du bruger den rigtige Python-fortolker.

Sørg for, at du installerer den korrekte mysql-connector-python pakke, som er en ren Python-implementering. Pas på med lignende navngivne, men nu afskrevne forbindelser som mysql-connector .




Etablering af en forbindelse med MySQL Server

MySQL er en serverbaseret databasestyringssystem. En server kan indeholde flere databaser. For at interagere med en database skal du først oprette forbindelse til serveren. Den generelle arbejdsgang for et Python-program, der interagerer med en MySQL-baseret database, er som følger:

  1. Opret forbindelse til MySQL-serveren.
  2. Opret en ny database.
  3. Opret forbindelse til den nyoprettede eller en eksisterende database.
  4. Udfør en SQL-forespørgsel, og hent resultater.
  5. Informer databasen, hvis der er foretaget ændringer i en tabel.
  6. Luk forbindelsen til MySQL-serveren.

Dette er en generisk arbejdsgang, der kan variere afhængigt af den enkelte applikation. Men uanset hvilken applikation der er, er det første skridt at forbinde din database med din applikation.


Etablering af en forbindelse

Det første trin i at interagere med en MySQL-server er at etablere en forbindelse. For at gøre dette skal du bruge connect() fra mysql.connector modul. Denne funktion tager parametre som host ind , user , og password og returnerer en MySQLConnection objekt. Du kan modtage disse legitimationsoplysninger som input fra brugeren og videregive dem til connect() :

from getpass import getpass
from mysql.connector import connect, Error

try:
    with connect(
        host="localhost",
        user=input("Enter username: "),
        password=getpass("Enter password: "),
    ) as connection:
        print(connection)
except Error as e:
    print(e)

Ovenstående kode bruger de indtastede loginoplysninger til at oprette forbindelse til din MySQL-server. Til gengæld får du en MySQLConnection objekt, som er gemt i connection variabel. Fra nu af vil du bruge denne variabel til at få adgang til din MySQL-server.

Der er flere vigtige ting at bemærke i koden ovenfor:

  • Du bør altid forholde dig til de undtagelser, der kan blive rejst, mens du etablerer en forbindelse til MySQL-serveren. Det er derfor, du bruger en tryexcept bloker for at fange og udskrive eventuelle undtagelser, som du måtte støde på.

  • Du bør altid lukke forbindelsen, når du er færdig med at få adgang til databasen. At efterlade ubrugte åbne forbindelser kan føre til flere uventede fejl og ydeevneproblemer. Ovenstående kode drager fordel af en konteksthåndtering, der bruger with , som abstraherer forbindelsesoprydningsprocessen.

  • Du bør aldrig hårdkode dine loginoplysninger , det vil sige dit brugernavn og adgangskode, direkte i et Python-script. Dette er en dårlig praksis for implementering og udgør en alvorlig sikkerhedstrussel. Koden ovenfor beder brugeren om login-legitimationsoplysninger. Den bruger den indbyggede getpass modul for at skjule adgangskoden. Selvom dette er bedre end hårdkodning, er der andre, mere sikre måder at gemme følsomme oplysninger på, såsom at bruge miljøvariabler.

Du har nu etableret en forbindelse mellem dit program og din MySQL-server, men du skal stadig enten oprette en ny database eller oprette forbindelse til en eksisterende database inde på serveren.



Oprettelse af en ny database

I det sidste afsnit oprettede du en forbindelse til din MySQL-server. For at oprette en ny database skal du udføre en SQL-sætning:

CREATE DATABASE books_db;

Ovenstående sætning vil oprette en ny database med navnet books_db .

Bemærk: I MySQL er det obligatorisk at sætte et semikolon (; ) i slutningen af ​​en sætning, som angiver afslutningen af ​​en forespørgsel. MySQL Connector/Python tilføjer dog automatisk et semikolon i slutningen af ​​dine forespørgsler, så det er ikke nødvendigt at bruge det i din Python-kode.

For at udføre en SQL-forespørgsel i Python skal du bruge en markør, som abstraherer adgangen til databaseposter. MySQL Connector/Python giver dig MySQLCursor klasse, som instansierer objekter, der kan udføre MySQL-forespørgsler i Python. En forekomst af MySQLCursor klasse kaldes også en cursor .

cursor objekter gør brug af en MySQLConnection objekt til at interagere med din MySQL-server. For at oprette en cursor , brug .cursor() metode til din connection variabel:

cursor = connection.cursor()

Ovenstående kode giver dig en forekomst af MySQLCursor klasse.

En forespørgsel, der skal udføres, sendes til cursor.execute() i strengformat. I denne særlige lejlighed sender du CREATE DATABASE forespørgsel til cursor.execute() :

from getpass import getpass
from mysql.connector import connect, Error

try:
    with connect(
        host="localhost",
        user=input("Enter username: "),
        password=getpass("Enter password: "),
    ) as connection:
        create_db_query = "CREATE DATABASE online_movie_rating"
        with connection.cursor() as cursor:
            cursor.execute(create_db_query)
except Error as e:
    print(e)

Efter at have udført koden ovenfor, har du en ny database kaldet online_movie_rating i din MySQL-server.

CREATE DATABASE forespørgslen er gemt som en streng i create_db_query variabel og derefter videregivet til cursor.execute() til udførelse. Koden bruger en konteksthåndtering med cursor objekt til at håndtere oprydningsprocessen.

Du får muligvis en fejlmeddelelse her, hvis der allerede findes en database med samme navn på din server. For at bekræfte dette kan du vise navnet på alle databaser på din server. Bruger den samme MySQLConnection objekt fra tidligere, skal du udføre SHOW DATABASES erklæring:

>>>
>>> show_db_query = "SHOW DATABASES"
>>> with connection.cursor() as cursor:
...     cursor.execute(show_db_query)
...     for db in cursor:
...         print(db)
...
('information_schema',)
('mysql',)
('online_movie_rating',)
('performance_schema',)
('sys',)

Ovenstående kode udskriver navnene på alle de databaser, der i øjeblikket findes på din MySQL-server. SHOW DATABASES kommandoen udsender også nogle databaser, som du ikke har oprettet på din server, såsom information_schema , performance_schema , og så videre. Disse databaser genereres automatisk af MySQL-serveren og giver adgang til en række forskellige databasemetadata og MySQL-serverindstillinger.

Du har oprettet en ny database i denne sektion ved at udføre CREATE DATABASE udmelding. I næste afsnit vil du se, hvordan du opretter forbindelse til en database, der allerede eksisterer.



Tilslutning til en eksisterende database

I det sidste afsnit oprettede du en ny database kaldet online_movie_rating . Du har dog stadig ikke oprettet forbindelse til det. I mange situationer har du allerede en MySQL-database, som du vil forbinde med din Python-applikation.

Du kan gøre dette ved at bruge den samme connect() funktion, som du brugte tidligere ved at sende en ekstra parameter kaldet database :

from getpass import getpass
from mysql.connector import connect, Error

try:
    with connect(
        host="localhost",
        user=input("Enter username: "),
        password=getpass("Enter password: "),
        database="online_movie_rating",
    ) as connection:
        print(connection)
except Error as e:
    print(e)

Ovenstående kode minder meget om forbindelsesscriptet, som du brugte tidligere. Den eneste ændring her er en ekstra database parameter, hvor navnet på din database sendes til connect() . Når du har udført dette script, bliver du forbundet til online_movie_rating database.




Oprettelse, ændring og sletning af en tabel

I dette afsnit lærer du, hvordan du udfører nogle grundlæggende DDL-forespørgsler såsom CREATE , DROP og ALTER med Python. Du får et hurtigt kig på MySQL-databasen, som du vil bruge i resten af ​​denne tutorial. Du vil også oprette alle de tabeller, der kræves til databasen, og lære, hvordan du udfører ændringer på disse tabeller senere.


Definition af databaseskemaet

Du kan starte med at oprette et databaseskema til et online filmvurderingssystem. Databasen vil bestå af tre tabeller:

  1. movies indeholder generel information om film og har følgende egenskaber:
    • id
    • title
    • release_year
    • genre
    • collection_in_mil
  2. reviewers indeholder oplysninger om personer, der har sendt anmeldelser eller vurderinger og har følgende egenskaber:
    • id
    • first_name
    • last_name
  3. ratings indeholder oplysninger om vurderinger, der er blevet sendt og har følgende attributter:
    • movie_id (fremmednøgle)
    • reviewer_id (fremmednøgle)
    • rating

Et filmvurderingssystem fra den virkelige verden, som IMDb, ville skulle gemme en masse andre attributter, såsom e-mails, filmbesætningslister og så videre. Hvis du vil, kan du tilføje flere tabeller og attributter til denne database. Men disse tre tabeller vil være tilstrækkelige til formålet med denne øvelse.

Billedet nedenfor viser databaseskemaet:

Tabellerne i denne database er relateret til hinanden. movies og reviewers vil have en mange-til-mange forhold, da én film kan anmeldes af flere anmeldere, og én anmelder kan anmelde flere film. ratings tabel forbinder movies tabel med reviewers tabel.



Oprettelse af tabeller ved hjælp af CREATE TABLE Erklæring

Nu, for at oprette en ny tabel i MySQL, skal du bruge CREATE TABLE udmelding. Følgende MySQL-forespørgsel vil skabe movies tabel for din online_movie_rating database:

CREATE TABLE movies(
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(100),
    release_year YEAR(4),
    genre VARCHAR(100),
    collection_in_mil INT
);

Hvis du har set på SQL-sætninger før, kan det meste af ovenstående forespørgsel give mening. Men der er nogle forskelle i MySQL-syntaksen, som du bør være opmærksom på.

For eksempel har MySQL en bred vifte af datatyper til din gennemlæsning, herunder YEAR , INT , BIGINT , og så videre. MySQL bruger også AUTO_INCREMENT nøgleord, når en kolonneværdi skal øges automatisk ved indsættelse af nye poster.

For at oprette en ny tabel skal du sende denne forespørgsel til cursor.execute() , som accepterer en MySQL-forespørgsel og udfører forespørgslen på den tilsluttede MySQL-database:

create_movies_table_query = """
CREATE TABLE movies(
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(100),
    release_year YEAR(4),
    genre VARCHAR(100),
    collection_in_mil INT
)
"""
with connection.cursor() as cursor:
    cursor.execute(create_movies_table_query)
    connection.commit()

Nu har du movies tabel i din database. Du sender create_movies_table_query til cursor.execute() , som udfører den nødvendige udførelse.

Bemærk: connection variabel refererer til MySQLConnection objekt, der blev returneret, da du oprettede forbindelse til din database.

Læg også mærke til connection.commit() erklæring i slutningen af ​​koden. Som standard forpligter din MySQL-connector ikke transaktioner automatisk. I MySQL forekommer ændringer nævnt i en transaktion kun, når du bruger en COMMIT kommando til sidst. Kald altid denne metode efter hver transaktion for at udføre ændringer i den faktiske tabel.

Som du gjorde med movies tabel, skal du udføre følgende script for at oprette reviewers tabel:

create_reviewers_table_query = """
CREATE TABLE reviewers (
    id INT AUTO_INCREMENT PRIMARY KEY,
    first_name VARCHAR(100),
    last_name VARCHAR(100)
)
"""
with connection.cursor() as cursor:
    cursor.execute(create_reviewers_table_query)
    connection.commit()

Hvis det er nødvendigt, kan du tilføje flere oplysninger om en anmelder, såsom deres e-mail-id eller demografiske oplysninger. Men first_name og last_name vil tjene dit formål for nu.

Endelig kan du oprette ratings tabel ved hjælp af følgende script:

create_ratings_table_query = """
CREATE TABLE ratings (
    movie_id INT,
    reviewer_id INT,
    rating DECIMAL(2,1),
    FOREIGN KEY(movie_id) REFERENCES movies(id),
    FOREIGN KEY(reviewer_id) REFERENCES reviewers(id),
    PRIMARY KEY(movie_id, reviewer_id)
)
"""
with connection.cursor() as cursor:
    cursor.execute(create_ratings_table_query)
    connection.commit()

Implementeringen af ​​udenlandske nøglerelationer i MySQL er lidt anderledes og begrænset sammenlignet med standard SQL. I MySQL skal både det overordnede og det underordnede i den fremmede nøgle-begrænsning bruge den samme lagermaskine .

En storage-motor er den underliggende softwarekomponent, som et databasestyringssystem bruger til at udføre SQL-operationer. I MySQL kommer lagringsmotorer i to forskellige varianter:

  1. Transaktionslagringsmotorer er transaktionssikre og giver dig mulighed for at rulle tilbage transaktioner ved hjælp af simple kommandoer som rollback . Mange populære MySQL-motorer, inklusive InnoDB og NDB, tilhører denne kategori.

  2. Ikke-transaktionelle lagringsmotorer afhænge af udførlig manuel kode for at fortryde udsagn begået på en database. MyISAM, MEMORY og mange andre MySQL-motorer er ikke-transaktionelle.

InnoDB er standard og mest populære lagermotor. Det hjælper med at bevare dataintegriteten ved at understøtte fremmednøglebegrænsninger. Dette betyder, at enhver CRUD-handling på en fremmednøgle kontrolleres for at sikre, at den ikke fører til uoverensstemmelser på tværs af forskellige tabeller.

Bemærk også, at ratings tabel bruger kolonnerne movie_id og reviewer_id , begge fremmednøgler, sammen som den primære nøgle . Dette trin sikrer, at en anmelder ikke kan bedømme den samme film to gange.

Du kan vælge at genbruge den samme markør til flere udførelser. I så fald ville alle henrettelser blive en atomtransaktion i stedet for flere separate transaktioner. For eksempel kan du udføre alle CREATE TABLE udsagn med én markør og derefter begå din transaktion kun én gang:

with connection.cursor() as cursor:
    cursor.execute(create_movies_table_query)
    cursor.execute(create_reviewers_table_query)
    cursor.execute(create_ratings_table_query)
    connection.commit()

Ovenstående kode vil først udføre alle tre CREATE udsagn. Så sender den en COMMIT kommando til MySQL-serveren, der begår din transaktion. Du kan også bruge .rollback() for at sende en ROLLBACK kommandoen til MySQL-serveren og fjern alle dataændringer fra transaktionen.



Visning af et tabelskema ved hjælp af DESCRIBE Erklæring

Nu, hvor du har oprettet alle tre tabeller, kan du se på deres skema ved hjælp af følgende SQL-sætning:

DESCRIBE <table_name>;

For at få nogle resultater tilbage fra cursor objekt, skal du bruge cursor.fetchall() . Denne metode henter alle rækker fra den sidst udførte sætning. Forudsat at du allerede har MySQLConnection objekt i connection variabel, kan du udskrive alle resultater hentet af cursor.fetchall() :

>>>
>>> show_table_query = "DESCRIBE movies"
>>> with connection.cursor() as cursor:
...     cursor.execute(show_table_query)
...     # Fetch rows from last executed query
...     result = cursor.fetchall()
...     for row in result:
...         print(row)
...
('id', 'int(11)', 'NO', 'PRI', None, 'auto_increment')
('title', 'varchar(100)', 'YES', '', None, '')
('release_year', 'year(4)', 'YES', '', None, '')
('genre', 'varchar(100)', 'YES', '', None, '')
('collection_in_mil', 'int(11)', 'YES', '', None, '')

Når du har udført ovenstående kode, bør du modtage en tabel med information om alle kolonnerne i movies bord. For hver kolonne modtager du detaljer som kolonnens datatype, om kolonnen er en primær nøgle og så videre.



Ændring af et tabelskema ved hjælp af ALTER Erklæring

I movies tabel, har du en kolonne kaldet collection_in_mil , som indeholder en films box office-samling i millioner af dollars. Du kan skrive følgende MySQL-sætning for at ændre datatypen collection_in_mil attribut fra INT til DECIMAL :

ALTER TABLE movies MODIFY COLUMN collection_in_mil DECIMAL(4,1);

DECIMAL(4,1) betyder et decimaltal, der maksimalt kan have 4 cifre, heraf 1 er decimal, såsom 120.1 , 3.4 , 38.0 , og så videre. Efter at have udført ALTER TABLE sætning, kan du vise det opdaterede tabelskema ved hjælp af DESCRIBE :

>>>
>>> alter_table_query = """
... ALTER TABLE movies
... MODIFY COLUMN collection_in_mil DECIMAL(4,1)
... """
>>> show_table_query = "DESCRIBE movies"
>>> with connection.cursor() as cursor:
...     cursor.execute(alter_table_query)
...     cursor.execute(show_table_query)
...     # Fetch rows from last executed query
...     result = cursor.fetchall()
...     print("Movie Table Schema after alteration:")
...     for row in result:
...         print(row)
...
Movie Table Schema after alteration
('id', 'int(11)', 'NO', 'PRI', None, 'auto_increment')
('title', 'varchar(100)', 'YES', '', None, '')
('release_year', 'year(4)', 'YES', '', None, '')
('genre', 'varchar(100)', 'YES', '', None, '')
('collection_in_mil', 'decimal(4,1)', 'YES', '', None, '')

Som vist i outputtet er collection_in_mil attribut er nu af typen DECIMAL(4,1) . Bemærk også, at du i koden ovenfor kalder cursor.execute() to gange. Men cursor.fetchall() henter rækker fra kun den sidst udførte forespørgsel, som er show_table_query .



Sletning af tabeller ved hjælp af DROP Erklæring

For at slette en tabel skal du udføre DROP TABLE erklæring i MySQL. Sletning af en tabel er en irreversibel behandle. Hvis du udfører koden nedenfor, skal du kalde CREATE TABLE forespørg igen for at bruge ratings tabel i de kommende afsnit.

For at slette ratings tabel, send drop_table_query til cursor.execute() :

drop_table_query = "DROP TABLE ratings"
with connection.cursor() as cursor:
    cursor.execute(drop_table_query)

Hvis du udfører ovenstående kode, vil du have slettet ratings tabel.




Indsættelse af poster i tabeller

I det sidste afsnit oprettede du tre tabeller i din database:movies , reviewers og ratings . Nu skal du udfylde disse tabeller med data. Dette afsnit vil dække to forskellige måder at indsætte poster i MySQL Connector til Python.

Den første metode, .execute() , fungerer godt, når antallet af poster er lille, og posterne kan hårdkodes. Den anden metode, .executemany() , er mere populær og er bedre egnet til scenarier i den virkelige verden.


Ved brug af .execute()

Den første tilgang bruger den samme cursor.execute() metode, du har brugt indtil nu. Du skriver INSERT INTO forespørgsel i en streng, og send den til cursor.execute() . Du kan bruge denne metode til at indsætte data i movies tabel.

Til reference, movies tabellen har fem attributter:

  1. id
  2. title
  3. release_year
  4. genre
  5. collection_in_mil

Du behøver ikke tilføje data for id som AUTO_INCREMENT beregner automatisk id for dig. Følgende script indsætter poster i movies tabel:

insert_movies_query = """
INSERT INTO movies (title, release_year, genre, collection_in_mil)
VALUES
    ("Forrest Gump", 1994, "Drama", 330.2),
    ("3 Idiots", 2009, "Drama", 2.4),
    ("Eternal Sunshine of the Spotless Mind", 2004, "Drama", 34.5),
    ("Good Will Hunting", 1997, "Drama", 138.1),
    ("Skyfall", 2012, "Action", 304.6),
    ("Gladiator", 2000, "Action", 188.7),
    ("Black", 2005, "Drama", 3.0),
    ("Titanic", 1997, "Romance", 659.2),
    ("The Shawshank Redemption", 1994, "Drama",28.4),
    ("Udaan", 2010, "Drama", 1.5),
    ("Home Alone", 1990, "Comedy", 286.9),
    ("Casablanca", 1942, "Romance", 1.0),
    ("Avengers: Endgame", 2019, "Action", 858.8),
    ("Night of the Living Dead", 1968, "Horror", 2.5),
    ("The Godfather", 1972, "Crime", 135.6),
    ("Haider", 2014, "Action", 4.2),
    ("Inception", 2010, "Adventure", 293.7),
    ("Evil", 2003, "Horror", 1.3),
    ("Toy Story 4", 2019, "Animation", 434.9),
    ("Air Force One", 1997, "Drama", 138.1),
    ("The Dark Knight", 2008, "Action",535.4),
    ("Bhaag Milkha Bhaag", 2013, "Sport", 4.1),
    ("The Lion King", 1994, "Animation", 423.6),
    ("Pulp Fiction", 1994, "Crime", 108.8),
    ("Kai Po Che", 2013, "Sport", 6.0),
    ("Beasts of No Nation", 2015, "War", 1.4),
    ("Andadhun", 2018, "Thriller", 2.9),
    ("The Silence of the Lambs", 1991, "Crime", 68.2),
    ("Deadpool", 2016, "Action", 363.6),
    ("Drishyam", 2015, "Mystery", 3.0)
"""
with connection.cursor() as cursor:
    cursor.execute(insert_movies_query)
    connection.commit()

The movies table is now loaded with thirty records. The code calls connection.commit() at the end. It’s crucial to call .commit() after preforming any modifications to a table.



Using .executemany()

The previous approach is more suitable when the number of records is fairly small and you can write these records directly into the code. But this is rarely true. You’ll often have this data stored in some other file, or the data will be generated by a different script and will need to be added to the MySQL database.

This is where .executemany() comes in handy. It accepts two parameters:

  1. A query that contains placeholders for the records that need to be inserted
  2. A list that contains all records that you wish to insert

The following example inserts records for the reviewers table:

insert_reviewers_query = """
INSERT INTO reviewers
(first_name, last_name)
VALUES ( %s, %s )
"""
reviewers_records = [
    ("Chaitanya", "Baweja"),
    ("Mary", "Cooper"),
    ("John", "Wayne"),
    ("Thomas", "Stoneman"),
    ("Penny", "Hofstadter"),
    ("Mitchell", "Marsh"),
    ("Wyatt", "Skaggs"),
    ("Andre", "Veiga"),
    ("Sheldon", "Cooper"),
    ("Kimbra", "Masters"),
    ("Kat", "Dennings"),
    ("Bruce", "Wayne"),
    ("Domingo", "Cortes"),
    ("Rajesh", "Koothrappali"),
    ("Ben", "Glocker"),
    ("Mahinder", "Dhoni"),
    ("Akbar", "Khan"),
    ("Howard", "Wolowitz"),
    ("Pinkie", "Petit"),
    ("Gurkaran", "Singh"),
    ("Amy", "Farah Fowler"),
    ("Marlon", "Crafford"),
]
with connection.cursor() as cursor:
    cursor.executemany(insert_reviewers_query, reviewers_records)
    connection.commit()

In the script above, you pass both the query and the list of records as arguments to .executemany() . These records could have been fetched from a file or from the user and stored in the reviewers_records list.

The code uses %s as a placeholder for the two strings that had to be inserted in the insert_reviewers_query . Placeholders act as format specifiers and help reserve a spot for a variable inside a string. The specified variable is then added to this spot during execution.

You can similarly use .executemany() to insert records in the ratings table:

insert_ratings_query = """
INSERT INTO ratings
(rating, movie_id, reviewer_id)
VALUES ( %s, %s, %s)
"""
ratings_records = [
    (6.4, 17, 5), (5.6, 19, 1), (6.3, 22, 14), (5.1, 21, 17),
    (5.0, 5, 5), (6.5, 21, 5), (8.5, 30, 13), (9.7, 6, 4),
    (8.5, 24, 12), (9.9, 14, 9), (8.7, 26, 14), (9.9, 6, 10),
    (5.1, 30, 6), (5.4, 18, 16), (6.2, 6, 20), (7.3, 21, 19),
    (8.1, 17, 18), (5.0, 7, 2), (9.8, 23, 3), (8.0, 22, 9),
    (8.5, 11, 13), (5.0, 5, 11), (5.7, 8, 2), (7.6, 25, 19),
    (5.2, 18, 15), (9.7, 13, 3), (5.8, 18, 8), (5.8, 30, 15),
    (8.4, 21, 18), (6.2, 23, 16), (7.0, 10, 18), (9.5, 30, 20),
    (8.9, 3, 19), (6.4, 12, 2), (7.8, 12, 22), (9.9, 15, 13),
    (7.5, 20, 17), (9.0, 25, 6), (8.5, 23, 2), (5.3, 30, 17),
    (6.4, 5, 10), (8.1, 5, 21), (5.7, 22, 1), (6.3, 28, 4),
    (9.8, 13, 1)
]
with connection.cursor() as cursor:
    cursor.executemany(insert_ratings_query, ratings_records)
    connection.commit()

All three tables are now populated with data. You now have a fully functional online movie rating database. The next step is to understand how to interact with this database.




Reading Records From the Database

Until now, you’ve been building your database. Now it’s time to perform some queries on it and find some interesting properties from this dataset. In this section, you’ll learn how to read records from database tables using the SELECT statement.


Reading Records Using the SELECT Statement

To retrieve records, you need to send a SELECT query to cursor.execute() . Then you use cursor.fetchall() to extract the retrieved table in the form of a list of rows or records.

Try writing a MySQL query to select all records from the movies table and send it to .execute() :

>>>
>>> select_movies_query = "SELECT * FROM movies LIMIT 5"
>>> with connection.cursor() as cursor:
...     cursor.execute(select_movies_query)
...     result = cursor.fetchall()
...     for row in result:
...         print(row)
...
(1, 'Forrest Gump', 1994, 'Drama', Decimal('330.2'))
(2, '3 Idiots', 2009, 'Drama', Decimal('2.4'))
(3, 'Eternal Sunshine of the Spotless Mind', 2004, 'Drama', Decimal('34.5'))
(4, 'Good Will Hunting', 1997, 'Drama', Decimal('138.1'))
(5, 'Skyfall', 2012, 'Action', Decimal('304.6'))

The result variable holds the records returned from using .fetchall() . It’s a list of tuples representing individual records from the table.

In the query above, you use the LIMIT clause to constrain the number of rows that are received from the SELECT statement. Developers often use LIMIT to perform pagination when handling large volumes of data.

In MySQL, the LIMIT clause takes one or two nonnegative numeric arguments. When using one argument, you specify the maximum number of rows to return. Since your query includes LIMIT 5 , only the first 5 records are fetched. When using both arguments, you can also specify the offset of the first row to return:

SELECT * FROM movies LIMIT 2,5;

The first argument specifies an offset of 2 , and the second argument constrains the number of returned rows to 5 . The above query will return rows 3 to 7.

You can also query for selected columns:

>>>
>>> select_movies_query = "SELECT title, release_year FROM movies LIMIT 5"
>>> with connection.cursor() as cursor:
...     cursor.execute(select_movies_query)
...     for row in cursor.fetchall():
...         print(row)
...
('Forrest Gump', 1994)
('3 Idiots', 2009)
('Eternal Sunshine of the Spotless Mind', 2004)
('Good Will Hunting', 1997)
('Skyfall', 2012)

Now, the code outputs values only from the two specified columns:title and release_year .



Filtering Results Using the WHERE Clause

You can filter table records by specific criteria using the WHERE clause. For example, to retrieve all movies with a box office collection greater than $300 million, you could run the following query:

SELECT title, collection_in_mil
FROM movies
WHERE collection_in_mil > 300;

You can also use ORDER BY clause in the last query to sort the results from the highest to the lowest earner:

>>>
>>> select_movies_query = """
... SELECT title, collection_in_mil
... FROM movies
... WHERE collection_in_mil > 300
... ORDER BY collection_in_mil DESC
... """
>>> with connection.cursor() as cursor:
...     cursor.execute(select_movies_query)
...     for movie in cursor.fetchall():
...         print(movie)
...
('Avengers: Endgame', Decimal('858.8'))
('Titanic', Decimal('659.2'))
('The Dark Knight', Decimal('535.4'))
('Toy Story 4', Decimal('434.9'))
('The Lion King', Decimal('423.6'))
('Deadpool', Decimal('363.6'))
('Forrest Gump', Decimal('330.2'))
('Skyfall', Decimal('304.6'))

MySQL offers a plethora of string formatting operations like CONCAT for concatenating strings. Often, websites will show the movie title along with its release year to avoid confusion. To retrieve the titles of the top five grossing movies, concatenated with their release years, you can write the following query:

>>>
>>> select_movies_query = """
... SELECT CONCAT(title, " (", release_year, ")"),
...       collection_in_mil
... FROM movies
... ORDER BY collection_in_mil DESC
... LIMIT 5
... """
>>> with connection.cursor() as cursor:
...     cursor.execute(select_movies_query)
...     for movie in cursor.fetchall():
...         print(movie)
...
('Avengers: Endgame (2019)', Decimal('858.8'))
('Titanic (1997)', Decimal('659.2'))
('The Dark Knight (2008)', Decimal('535.4'))
('Toy Story 4 (2019)', Decimal('434.9'))
('The Lion King (1994)', Decimal('423.6'))

If you don’t want to use the LIMIT clause and you don’t need to fetch all the records, then the cursor object has .fetchone() and .fetchmany() methods as well:

  • .fetchone() retrieves either the next row of the result, as a tuple, or None if no more rows are available.
  • .fetchmany() retrieves the next set of rows from the result as a list of tuples. It has a size argument, which defaults to 1 , that you can use to specify the number of rows you need to fetch. If no more rows are available, then the method returns an empty list.

Try retrieving the titles of the five highest-grossing movies concatenated with their release years again, but this time use .fetchmany() :

>>>
>>> select_movies_query = """
... SELECT CONCAT(title, " (", release_year, ")"),
...       collection_in_mil
... FROM movies
... ORDER BY collection_in_mil DESC
... """
>>> with connection.cursor() as cursor:
...     cursor.execute(select_movies_query)
...     for movie in cursor.fetchmany(size=5):
...         print(movie)
...     cursor.fetchall()
...
('Avengers: Endgame (2019)', Decimal('858.8'))
('Titanic (1997)', Decimal('659.2'))
('The Dark Knight (2008)', Decimal('535.4'))
('Toy Story 4 (2019)', Decimal('434.9'))
('The Lion King (1994)', Decimal('423.6'))

The output with .fetchmany() is similar to what you received when you used the LIMIT clause. You might have noticed the additional cursor.fetchall() call at the end. You do this to clean all the remaining results that weren’t read by .fetchmany() .

It’s necessary to clean all unread results before executing any other statements on the same connection. Otherwise, an InternalError: Unread result found exception will be raised.




Handling Multiple Tables Using the JOIN Statement

If you found the queries in the last section to be quite straightforward, don’t worry. You can make your SELECT queries as complex as you want using the same methods from the last section.

Let’s look at some slightly more complex JOIN queries. If you want to find out the name of the top five highest-rated movies in your database, then you can run the following query:

>>>
>>> select_movies_query = """
... SELECT title, AVG(rating) as average_rating
... FROM ratings
... INNER JOIN movies
...     ON movies.id = ratings.movie_id
... GROUP BY movie_id
... ORDER BY average_rating DESC
... LIMIT 5
... """
>>> with connection.cursor() as cursor:
...     cursor.execute(select_movies_query)
...     for movie in cursor.fetchall():
...         print(movie)
...
('Night of the Living Dead', Decimal('9.90000'))
('The Godfather', Decimal('9.90000'))
('Avengers: Endgame', Decimal('9.75000'))
('Eternal Sunshine of the Spotless Mind', Decimal('8.90000'))
('Beasts of No Nation', Decimal('8.70000'))

As shown above, Night of the Living Dead and The Godfather are tied as the highest-rated movies in your online_movie_rating database.

To find the name of the reviewer who gave the most ratings, write the following query:

>>>
>>> select_movies_query = """
... SELECT CONCAT(first_name, " ", last_name), COUNT(*) as num
... FROM reviewers
... INNER JOIN ratings
...     ON reviewers.id = ratings.reviewer_id
... GROUP BY reviewer_id
... ORDER BY num DESC
... LIMIT 1
... """
>>> with connection.cursor() as cursor:
...     cursor.execute(select_movies_query)
...     for movie in cursor.fetchall():
...         print(movie)
...
('Mary Cooper', 4)

Mary Cooper is the most frequent reviewer in this database. As seen above, it doesn’t matter how complicated the query is because it’s ultimately handled by the MySQL server. Your process for executing a query will always remain the same:pass the query to cursor.execute() and fetch the results using .fetchall() .



Updating and Deleting Records From the Database

In this section, you’ll be updating and deleting records from the database. Both of these operations can be performed on either a single record or multiple records in the table. You’ll select the rows that need to be modified using the WHERE klausul.


UPDATE Command

One of the reviewers in your database, Amy Farah Fowler , is now married to Sheldon Cooper . Her last name has now changed to Cooper , so you need to update your database accordingly. For updating records, MySQL uses the UPDATE statement:

update_query = """
UPDATE
    reviewers
SET
    last_name = "Cooper"
WHERE
    first_name = "Amy"
"""
with connection.cursor() as cursor:
    cursor.execute(update_query)
    connection.commit()

The code passes the update query to cursor.execute() , and .commit() brings the required changes to the reviewers table.

Note: In the UPDATE query, the WHERE clause helps specify the records that need to be updated. If you don’t use WHERE , then all records will be updated!

Suppose you need to provide an option that allows reviewers to modify ratings. A reviewer will provide three values, movie_id , reviewer_id , and the new rating . The code will display the record after performing the specified modification.

Assuming that movie_id = 18 , reviewer_id = 15 , and the new rating = 5.0 , you can use the following MySQL queries to perform the required modification:

UPDATE
    ratings
SET
    rating = 5.0
WHERE
    movie_id = 18 AND reviewer_id = 15;

SELECT *
FROM ratings
WHERE
    movie_id = 18 AND reviewer_id = 15;

The above queries first update the rating and then display it. You can create a complete Python script that establises a connection with the database and allows the reviewer to modify a rating:

from getpass import getpass
from mysql.connector import connect, Error

movie_id = input("Enter movie id: ")
reviewer_id = input("Enter reviewer id: ")
new_rating = input("Enter new rating: ")
update_query = """
UPDATE
    ratings
SET
    rating = "%s"
WHERE
    movie_id = "%s" AND reviewer_id = "%s";

SELECT *
FROM ratings
WHERE
    movie_id = "%s" AND reviewer_id = "%s"
""" % (
    new_rating,
    movie_id,
    reviewer_id,
    movie_id,
    reviewer_id,
)

try:
    with connect(
        host="localhost",
        user=input("Enter username: "),
        password=getpass("Enter password: "),
        database="online_movie_rating",
    ) as connection:
        with connection.cursor() as cursor:
            for result in cursor.execute(update_query, multi=True):
                if result.with_rows:
                    print(result.fetchall())
            connection.commit()
except Error as e:
    print(e)

Save this code to a file named modify_ratings.py . The above code uses %s placeholders to insert the received input in the update_query string. For the first time in this tutorial, you have multiple queries inside a single string. To pass multiple queries to a single cursor.execute() , you need to set the method’s multi argument to True .

If multi is True , then cursor.execute() returns an iterator. Each item in the iterator corresponds to a cursor object that executes a statement passed in the query. The above code runs a for loop on this iterator and then calls .fetchall() on each cursor object.

Note: Running .fetchall() on all cursor objects is important. To execute a new statement on the same connection, you must ensure that there are no unread results from previous executions. If there are unread results, then you’ll receive an exception.

If no result set is fetched on an operation, then .fetchall() raises an exception. To avoid this error, in the code above you use the cursor.with_rows property, which indicates whether the most recently executed operation produced rows.

While this code should solve your purpose, the WHERE clause is a prime target for web hackers in its current state. It’s vulnerable to what is called a SQL injection attack, which can allow malicious actors to either corrupt or misuse your database.

Warning :Don’t try the below inputs on your database! They will corrupt your table and you’ll need to recreate it.

For example, if a user sends movie_id=18 , reviewer_id=15 , and the new rating=5.0 as input, then the output looks like this:

$ python modify_ratings.py
Enter movie id: 18
Enter reviewer id: 15
Enter new rating: 5.0
Enter username: <user_name>
Enter password:
[(18, 15, Decimal('5.0'))]

The rating with movie_id=18 and reviewer_id=15 has been changed to 5.0 . But if you were hacker, then you might send a hidden command in your input:

$ python modify_ratings.py
Enter movie id: 18
Enter reviewer id: 15"; UPDATE reviewers SET last_name = "A
Enter new rating: 5.0
Enter username: <user_name>
Enter password:
[(18, 15, Decimal('5.0'))]

Again, the output shows that the specified rating has been changed to 5.0 . What’s changed?

The hacker sneaked in an update query while entering the reviewer_id . The update query, update reviewers set last_name = "A , changes the last_name of all records in the reviewers table to "A" . You can see this change if you print out the reviewers table:

>>>
>>> select_query = """
... SELECT first_name, last_name
... FROM reviewers
... """
>>> with connection.cursor() as cursor:
...     cursor.execute(select_query)
...     for reviewer in cursor.fetchall():
...         print(reviewer)
...
('Chaitanya', 'A')
('Mary', 'A')
('John', 'A')
('Thomas', 'A')
('Penny', 'A')
('Mitchell', 'A')
('Wyatt', 'A')
('Andre', 'A')
('Sheldon', 'A')
('Kimbra', 'A')
('Kat', 'A')
('Bruce', 'A')
('Domingo', 'A')
('Rajesh', 'A')
('Ben', 'A')
('Mahinder', 'A')
('Akbar', 'A')
('Howard', 'A')
('Pinkie', 'A')
('Gurkaran', 'A')
('Amy', 'A')
('Marlon', 'A')

The above code displays the first_name and last_name for all records in the reviewers table. The SQL injection attack corrupted this table by changing the last_name of all records to "A" .

There’s a quick fix to prevent such attacks. Don’t add the query values provided by the user directly to your query string. Instead, update the modify_ratings.py script to send these query values as arguments to .execute() :

from getpass import getpass
from mysql.connector import connect, Error

movie_id = input("Enter movie id: ")
reviewer_id = input("Enter reviewer id: ")
new_rating = input("Enter new rating: ")
update_query = """
UPDATE
    ratings
SET
    rating = %s
WHERE
    movie_id = %s AND reviewer_id = %s;

SELECT *
FROM ratings
WHERE
    movie_id = %s AND reviewer_id = %s
"""
val_tuple = (
    new_rating,
    movie_id,
    reviewer_id,
    movie_id,
    reviewer_id,
)

try:
    with connect(
        host="localhost",
        user=input("Enter username: "),
        password=getpass("Enter password: "),
        database="online_movie_rating",
    ) as connection:
        with connection.cursor() as cursor:
            for result in cursor.execute(update_query, val_tuple, multi=True):
                if result.with_rows:
                    print(result.fetchall())
            connection.commit()
except Error as e:
    print(e)

Notice that the %s placeholders are no longer in string quotes. Strings passed to the placeholders might contain some special characters. If necessary, these can be correctly escaped by the underlying library.

cursor.execute() makes sure that the values in the tuple received as argument are of the required data type. If a user tries to sneak in some problematic characters, then the code will raise an exception:

$ python modify_ratings.py
Enter movie id: 18
Enter reviewer id: 15"; UPDATE reviewers SET last_name = "A
Enter new rating: 5.0
Enter username: <user_name>
Enter password:
1292 (22007): Truncated incorrect DOUBLE value: '15";
UPDATE reviewers SET last_name = "A'

cursor.execute() will raise an exception if it finds any unwanted characters in the user input. You should use this approach whenever you incorporate user input in a query. There are other ways of preventing SQL injection attacks as well.



DELETE Command

Deleting records works very similarly to updating records. You use the DELETE statement to remove selected records.

Note: Deleting is an irreversible behandle. If you don’t use the WHERE clause, then all records from the specified table will be deleted. You’ll need to run the INSERT INTO query again to get back the deleted records.

It’s recommended that you first run a SELECT query with the same filter to make sure that you’re deleting the right records. For example, to remove all ratings given by reviewer_id = 2 , you should first run the corresponding SELECT query:

>>>
>>> select_movies_query = """
... SELECT reviewer_id, movie_id FROM ratings
... WHERE reviewer_id = 2
... """
>>> with connection.cursor() as cursor:
...     cursor.execute(select_movies_query)
...     for movie in cursor.fetchall():
...         print(movie)
...
(2, 7)
(2, 8)
(2, 12)
(2, 23)

The above code snippet outputs the reviewer_id and movie_id for records in the ratings table where reviewer_id = 2 . Once you’ve confirmed that these are the records that you need to delete, you can run a DELETE query with the same filter:

delete_query = "DELETE FROM ratings WHERE reviewer_id = 2"
with connection.cursor() as cursor:
    cursor.execute(delete_query)
    connection.commit()

With this query, you remove all ratings given by the reviewer with reviewer_id = 2 from the ratings table.




Other Ways to Connect Python and MySQL

In this tutorial, you saw MySQL Connector/Python, which is the officially recommended means of interacting with a MySQL database from a Python application. There are two other popular connectors:

  1. mysqlclient is a library that is a close competitor to the official connector and is actively updated with new features. Because its core is written in C, it has better performance than the pure-Python official connector. A big drawback is that it’s fairly difficult to set up and install, especially on Windows.

  2. MySQLdb is a legacy software that’s still used in commercial applications. It’s written in C and is faster than MySQL Connector/Python but is available only for Python 2.

These connectors act as interfaces between your program and a MySQL database, and you send your SQL queries through them. But many developers prefer using an object-oriented paradigm rather than SQL queries to manipulate data.

Object-relational mapping (ORM) is a technique that allows you to query and manipulate data from a database directly using an object-oriented language. An ORM library encapsulates the code needed to manipulate data, which eliminates the need to use even a tiny bit of SQL. Here are the most popular Python ORMs for SQL-based databases:

  1. SQLAlchemy is an ORM that facilitates communication between Python and other SQL databases. You can create different engines for different databases like MySQL, PostgreSQL, SQLite, and so on. SQLAlchemy is commonly used alongside the pandas library to provide complete data-handling functionality.

  2. peewee is a lightweight and fast ORM that’s quick to set up. This is quite useful when your interaction with the database is limited to extracting a few records. For example, if you need to copy selected records from a MySQL database into a CSV file, then peewee might be your best choice.

  3. Django ORM is one of the most powerful features of Django and is supplied alongside the Django web framework. It can interact with a variety of databases such as SQLite, PostgreSQL, and MySQL. Many Django-based applications use the Django ORM for data modeling and basic queries but often switch to SQLAlchemy for more complex requirements.

You might find one of these approaches to be more suitable for your application. If you’re not sure which one to use, then it’s best to go with the officially recommended MySQL Connector/Python that you saw in action in this tutorial.



Conclusion

In this tutorial, you saw how to use MySQL Connector/Python to integrate a MySQL database with your Python application. You also saw some unique features of a MySQL database that differentiate it from other SQL databases.

Along the way, you learned some programming best practices that are worth considering when it comes to establishing a connection, creating tables, and inserting and updating records in a database application. You also developed a sample MySQL database for an online movie rating system and interacted with it directly from your Python application.

In this tutorial, you learned how to:

  • Connect your Python app with a MySQL database
  • Bring data from a MySQL database into Python for further analysis
  • Execute SQL queries from your Python application
  • Handle exceptions while accessing the database
  • Prevent SQL injection attacks on your application

If you’re interested, Python also has connectors for other DBMSs like MongoDB and PostgreSQL. For more information, check out Python Database Tutorials.



  1. Hvordan migrerer man en PostgreSQL-database til en SQLServer-database?

  2. Sådan aktiveres MySQL Query Cache

  3. Funktion til at returnere dynamisk sæt af kolonner for en given tabel

  4. Hvordan får man første og sidste post fra en sql-forespørgsel?