Python e SQL são duas das linguagens mais importantes para analistas de dados.
Neste artigo, mostrarei tudo o que você precisa saber para conectar Python e SQL.
Você aprenderá a extrair dados de bancos de dados relacionais diretamente em seus pipelines de aprendizado de máquina, armazenar dados de seu aplicativo Python em um banco de dados próprio ou qualquer outro caso de uso que possa surgir.
Juntos vamos cobrir:
- Por que aprender a usar Python e SQL juntos?
- Como configurar seu ambiente Python e MySQL Server
- Conectando ao MySQL Server em Python
- Criando um novo banco de dados
- Criando tabelas e relacionamentos de tabelas
- Preenchendo tabelas com dados
- Dados de leitura
- Atualizando registros
- Exclusão de registros
- Criando registros a partir de listas do Python
- Criando funções reutilizáveis para fazer tudo isso para nós no futuro
Isso é um monte de coisas muito úteis e muito legais. Vamos entrar nisso!
Uma nota rápida antes de começarmos:há um Jupyter Notebook contendo todo o código usado neste tutorial disponível neste repositório do GitHub. Codificar junto é altamente recomendado!
O banco de dados e o código SQL usados aqui são todos da minha série anterior de Introdução ao SQL postada no Towards Data Science (entre em contato comigo se tiver algum problema para visualizar os artigos e posso enviar um link para vê-los gratuitamente).
Se você não estiver familiarizado com SQL e os conceitos por trás de bancos de dados relacionais, eu indicaria essa série (além disso, é claro que há uma enorme quantidade de coisas excelentes disponíveis aqui no freeCodeCamp!)
Por que Python com SQL?
Para analistas de dados e cientistas de dados, o Python tem muitas vantagens. Uma enorme variedade de bibliotecas de código aberto o torna uma ferramenta incrivelmente útil para qualquer analista de dados.
Temos pandas, NumPy e Vaex para análise de dados, Matplotlib, seaborn e Bokeh para visualização e TensorFlow, scikit-learn e PyTorch para aplicativos de aprendizado de máquina (além de muitos, muitos mais).
Com sua curva de aprendizado (relativamente) fácil e versatilidade, não é de admirar que o Python seja uma das linguagens de programação que mais crescem no mercado.
Portanto, se estivermos usando Python para análise de dados, vale a pena perguntar - de onde vêm todos esses dados?
Embora haja uma enorme variedade de fontes para conjuntos de dados, em muitos casos - principalmente em empresas - os dados serão armazenados em um banco de dados relacional. Os bancos de dados relacionais são uma maneira extremamente eficiente, poderosa e amplamente utilizada para criar, ler, atualizar e excluir dados de todos os tipos.
Os sistemas de gerenciamento de banco de dados relacional (RDBMSs) mais usados - Oracle, MySQL, Microsoft SQL Server, PostgreSQL, IBM DB2 - todos usam a Linguagem de Consulta Estruturada (SQL) para acessar e fazer alterações nos dados.
Observe que cada RDBMS usa um tipo de SQL ligeiramente diferente, portanto, o código SQL escrito para um geralmente não funcionará em outro sem modificações (normalmente pequenas). Mas os conceitos, estruturas e operações são em grande parte idênticos.
Isso significa que, para um analista de dados ativo, um forte entendimento do SQL é extremamente importante. Saber como usar Python e SQL juntos lhe dará ainda mais vantagem quando se trata de trabalhar com seus dados.
O restante deste artigo será dedicado a mostrar exatamente como podemos fazer isso.
Primeiros passos
Requisitos e instalação
Para codificar junto com este tutorial, você precisará do seu próprio ambiente Python configurado.
Eu uso o Anaconda, mas há muitas maneiras de fazer isso. Basta pesquisar no Google "como instalar o Python" se precisar de mais ajuda. Você também pode usar o Binder para codificar junto com o Jupyter Notebook associado.
Usaremos o MySQL Community Server, pois é gratuito e amplamente utilizado na indústria. Se você estiver usando o Windows, este guia o ajudará a configurar. Aqui estão guias para usuários de Mac e Linux também (embora possa variar de acordo com a distribuição do Linux).
Depois de configurá-los, precisaremos fazer com que eles se comuniquem.
Para isso, precisamos instalar a biblioteca Python do MySQL Connector. Para fazer isso, siga as instruções ou apenas use pip:
pip install mysql-connector-python
Também usaremos pandas, portanto, certifique-se de instalá-lo também.
pip install pandas
Importando bibliotecas
Como em todo projeto em Python, a primeira coisa que queremos fazer é importar nossas bibliotecas.
É uma prática recomendada importar todas as bibliotecas que vamos usar no início do projeto, para que as pessoas que leem ou revisem nosso código saibam mais ou menos o que está por vir, para que não haja surpresas.
Para este tutorial, usaremos apenas duas bibliotecas - MySQL Connector e pandas.
import mysql.connector
from mysql.connector import Error
import pandas as pd
Importamos a função Error separadamente para que tenhamos acesso fácil a ela para nossas funções.
Conectando ao servidor MySQL
A essa altura, devemos ter o MySQL Community Server configurado em nosso sistema. Agora precisamos escrever algum código em Python que nos permita estabelecer uma conexão com esse servidor.
def create_server_connection(host_name, user_name, user_password):
connection = None
try:
connection = mysql.connector.connect(
host=host_name,
user=user_name,
passwd=user_password
)
print("MySQL Database connection successful")
except Error as err:
print(f"Error: '{err}'")
return connection
Criar uma função reutilizável para código como esse é uma prática recomendada, para que possamos usá-la repetidamente com o mínimo de esforço. Uma vez que isso esteja escrito, você também poderá reutilizá-lo em todos os seus projetos no futuro, então, no futuro, você ficará grato!
Vamos passar por esta linha por linha para entendermos o que está acontecendo aqui:
A primeira linha é nós nomeando a função (create_server_connection) e nomeando os argumentos que essa função terá (host_name, user_name e user_password).
A próxima linha fecha todas as conexões existentes para que o servidor não fique confuso com várias conexões abertas.
Em seguida, usamos um bloco try-except do Python para lidar com possíveis erros. A primeira parte tenta criar uma conexão com o servidor usando o método mysql.connector.connect() usando os detalhes especificados pelo usuário nos argumentos. Se isso funcionar, a função imprime uma pequena mensagem de sucesso.
A parte except do bloco imprime o erro que o MySQL Server retorna, na infeliz circunstância de haver um erro.
Por fim, se a conexão for bem-sucedida, a função retornará um objeto de conexão.
Usamos isso na prática atribuindo a saída da função a uma variável, que então se torna nosso objeto de conexão. Podemos então aplicar outros métodos (como cursor) a ele e criar outros objetos úteis.
connection = create_server_connection("localhost", "root", pw)
Isso deve produzir uma mensagem de sucesso:
Criando um novo banco de dados
Agora que estabelecemos uma conexão, nosso próximo passo é criar um novo banco de dados em nosso servidor.
Neste tutorial, faremos isso apenas uma vez, mas novamente escreveremos isso como uma função reutilizável para que tenhamos uma boa função útil que podemos reutilizar em projetos futuros.
def create_database(connection, query):
cursor = connection.cursor()
try:
cursor.execute(query)
print("Database created successfully")
except Error as err:
print(f"Error: '{err}'")
Essa função recebe dois argumentos, connection (nosso objeto de conexão) e query (uma consulta SQL que escreveremos na próxima etapa). Ele executa a consulta no servidor através da conexão.
Usamos o método cursor em nosso objeto de conexão para criar um objeto cursor (o MySQL Connector usa um paradigma de programação orientada a objetos, portanto, há muitos objetos herdando propriedades de objetos pai).
Este objeto cursor possui métodos como execute, executemany (que usaremos neste tutorial) junto com vários outros métodos úteis.
Se isso ajudar, podemos pensar no objeto cursor como fornecendo acesso ao cursor piscante em uma janela de terminal do MySQL Server.
Em seguida, definimos uma consulta para criar o banco de dados e chamar a função:
Todas as consultas SQL usadas neste tutorial são explicadas em minha série de tutoriais Introdução ao SQL, e o código completo pode ser encontrado no Jupyter Notebook associado neste repositório do GitHub, portanto, não fornecerei explicações sobre o que o código SQL faz neste tutorial.
Esta é talvez a consulta SQL mais simples possível, no entanto. Se você pode ler em inglês, provavelmente pode descobrir o que ele faz!
Executar a função create_database com os argumentos acima resulta em um banco de dados chamado 'school' sendo criado em nosso servidor.
Por que nosso banco de dados é chamado de 'escola'? Talvez agora seja um bom momento para examinar com mais detalhes exatamente o que vamos implementar neste tutorial.
Nosso banco de dados
Seguindo o exemplo da minha série anterior, vamos implementar o banco de dados da International Language School - uma escola de treinamento de idiomas fictícia que oferece aulas de idiomas profissionais para clientes corporativos.
Este Entity Relationship Diagram (ERD) apresenta nossas entidades (Professor, Cliente, Curso e Participante) e define as relações entre elas.
Todas as informações sobre o que é um ERD e o que considerar ao criar um e projetar um banco de dados podem ser encontradas neste artigo.
O código SQL bruto, os requisitos do banco de dados e os dados a serem inseridos no banco de dados estão todos contidos neste repositório do GitHub, mas você também verá tudo isso ao longo deste tutorial.
Conectando ao banco de dados
Agora que criamos um banco de dados no MySQL Server, podemos modificar nossa função create_server_connection para conectar diretamente a esse banco de dados.
Observe que é possível - comum, na verdade - ter vários bancos de dados em um servidor MySQL, então queremos sempre e automaticamente nos conectar ao banco de dados em que estamos interessados.
Podemos fazer assim:
def create_db_connection(host_name, user_name, user_password, db_name):
connection = None
try:
connection = mysql.connector.connect(
host=host_name,
user=user_name,
passwd=user_password,
database=db_name
)
print("MySQL Database connection successful")
except Error as err:
print(f"Error: '{err}'")
return connection
Esta é exatamente a mesma função, mas agora pegamos mais um argumento - o nome do banco de dados - e passamos isso como um argumento para o método connect().
Criando uma função de execução de consulta
A função final que vamos criar (por enquanto) é extremamente vital - uma função de execução de consulta. Isso vai pegar nossas consultas SQL, armazenadas em Python como strings, e passá-las para o método cursor.execute() para executá-las no servidor.
def execute_query(connection, query):
cursor = connection.cursor()
try:
cursor.execute(query)
connection.commit()
print("Query successful")
except Error as err:
print(f"Error: '{err}'")
Essa função é exatamente igual à nossa função create_database anterior, exceto que ela usa o método connection.commit() para garantir que os comandos detalhados em nossas consultas SQL sejam implementados.
Esta será a nossa função de cavalo de batalha, que usaremos (junto com create_db_connection) para criar tabelas, estabelecer relacionamentos entre essas tabelas, preencher as tabelas com dados e atualizar e excluir registros em nosso banco de dados.
Se você é um especialista em SQL, esta função permitirá que você execute todos e quaisquer comandos e consultas complexas que você possa ter, diretamente de um script Python. Esta pode ser uma ferramenta muito poderosa para gerenciar seus dados.
Criando tabelas
Agora estamos prontos para começar a executar comandos SQL em nosso servidor e começar a construir nosso banco de dados. A primeira coisa que queremos fazer é criar as tabelas necessárias.
Vamos começar com a nossa tabela Professor:
create_teacher_table = """
CREATE TABLE teacher (
teacher_id INT PRIMARY KEY,
first_name VARCHAR(40) NOT NULL,
last_name VARCHAR(40) NOT NULL,
language_1 VARCHAR(3) NOT NULL,
language_2 VARCHAR(3),
dob DATE,
tax_id INT UNIQUE,
phone_no VARCHAR(20)
);
"""
connection = create_db_connection("localhost", "root", pw, db) # Connect to the Database
execute_query(connection, create_teacher_table) # Execute our defined query
Em primeiro lugar, atribuímos nosso comando SQL (explicado em detalhes aqui) a uma variável com um nome apropriado.
Nesse caso, usamos a notação de aspas triplas do Python para strings de várias linhas para armazenar nossa consulta SQL, então a alimentamos em nossa função execute_query para implementá-la.
Observe que essa formatação de várias linhas é puramente para o benefício de humanos lendo nosso código. Nem SQL nem Python 'se importam' se o comando SQL estiver espalhado assim. Desde que a sintaxe esteja correta, ambas as linguagens a aceitarão.
No entanto, para o benefício dos humanos que lerão seu código (mesmo que isso seja apenas você no futuro!), é muito útil fazer isso para tornar o código mais legível e compreensível.
O mesmo vale para a CAPITALIZAÇÃO de operadores em SQL. Esta é uma convenção amplamente utilizada que é fortemente recomendada, mas o software real que executa o código não diferencia maiúsculas de minúsculas e tratará 'CREATE TABLE teacher' e 'create table teacher' como comandos idênticos.
A execução deste código nos dá nossas mensagens de sucesso. Também podemos verificar isso no MySQL Server Command Line Client:
Excelente! Agora vamos criar as tabelas restantes.
create_client_table = """
CREATE TABLE client (
client_id INT PRIMARY KEY,
client_name VARCHAR(40) NOT NULL,
address VARCHAR(60) NOT NULL,
industry VARCHAR(20)
);
"""
create_participant_table = """
CREATE TABLE participant (
participant_id INT PRIMARY KEY,
first_name VARCHAR(40) NOT NULL,
last_name VARCHAR(40) NOT NULL,
phone_no VARCHAR(20),
client INT
);
"""
create_course_table = """
CREATE TABLE course (
course_id INT PRIMARY KEY,
course_name VARCHAR(40) NOT NULL,
language VARCHAR(3) NOT NULL,
level VARCHAR(2),
course_length_weeks INT,
start_date DATE,
in_school BOOLEAN,
teacher INT,
client INT
);
"""
connection = create_db_connection("localhost", "root", pw, db)
execute_query(connection, create_client_table)
execute_query(connection, create_participant_table)
execute_query(connection, create_course_table)
Isso cria as quatro tabelas necessárias para nossas quatro entidades.
Agora queremos definir os relacionamentos entre eles e criar mais uma tabela para lidar com o relacionamento muitos-para-muitos entre as tabelas do participante e do curso (veja aqui para mais detalhes).
Fazemos exatamente da mesma forma:
alter_participant = """
ALTER TABLE participant
ADD FOREIGN KEY(client)
REFERENCES client(client_id)
ON DELETE SET NULL;
"""
alter_course = """
ALTER TABLE course
ADD FOREIGN KEY(teacher)
REFERENCES teacher(teacher_id)
ON DELETE SET NULL;
"""
alter_course_again = """
ALTER TABLE course
ADD FOREIGN KEY(client)
REFERENCES client(client_id)
ON DELETE SET NULL;
"""
create_takescourse_table = """
CREATE TABLE takes_course (
participant_id INT,
course_id INT,
PRIMARY KEY(participant_id, course_id),
FOREIGN KEY(participant_id) REFERENCES participant(participant_id) ON DELETE CASCADE,
FOREIGN KEY(course_id) REFERENCES course(course_id) ON DELETE CASCADE
);
"""
connection = create_db_connection("localhost", "root", pw, db)
execute_query(connection, alter_participant)
execute_query(connection, alter_course)
execute_query(connection, alter_course_again)
execute_query(connection, create_takescourse_table)
Agora nossas tabelas são criadas, juntamente com as restrições apropriadas, chave primária e relações de chave estrangeira.
Preenchendo as tabelas
A próxima etapa é adicionar alguns registros às tabelas. Novamente, usamos execute_query para alimentar nossos comandos SQL existentes no servidor. Vamos começar novamente com a tabela Professor.
pop_teacher = """
INSERT INTO teacher VALUES
(1, 'James', 'Smith', 'ENG', NULL, '1985-04-20', 12345, '+491774553676'),
(2, 'Stefanie', 'Martin', 'FRA', NULL, '1970-02-17', 23456, '+491234567890'),
(3, 'Steve', 'Wang', 'MAN', 'ENG', '1990-11-12', 34567, '+447840921333'),
(4, 'Friederike', 'Müller-Rossi', 'DEU', 'ITA', '1987-07-07', 45678, '+492345678901'),
(5, 'Isobel', 'Ivanova', 'RUS', 'ENG', '1963-05-30', 56789, '+491772635467'),
(6, 'Niamh', 'Murphy', 'ENG', 'IRI', '1995-09-08', 67890, '+491231231232');
"""
connection = create_db_connection("localhost", "root", pw, db)
execute_query(connection, pop_teacher)
Isto funciona? Podemos verificar novamente em nosso MySQL Command Line Client:
Agora para preencher as tabelas restantes.
pop_client = """
INSERT INTO client VALUES
(101, 'Big Business Federation', '123 Falschungstraße, 10999 Berlin', 'NGO'),
(102, 'eCommerce GmbH', '27 Ersatz Allee, 10317 Berlin', 'Retail'),
(103, 'AutoMaker AG', '20 Künstlichstraße, 10023 Berlin', 'Auto'),
(104, 'Banko Bank', '12 Betrugstraße, 12345 Berlin', 'Banking'),
(105, 'WeMoveIt GmbH', '138 Arglistweg, 10065 Berlin', 'Logistics');
"""
pop_participant = """
INSERT INTO participant VALUES
(101, 'Marina', 'Berg','491635558182', 101),
(102, 'Andrea', 'Duerr', '49159555740', 101),
(103, 'Philipp', 'Probst', '49155555692', 102),
(104, 'René', 'Brandt', '4916355546', 102),
(105, 'Susanne', 'Shuster', '49155555779', 102),
(106, 'Christian', 'Schreiner', '49162555375', 101),
(107, 'Harry', 'Kim', '49177555633', 101),
(108, 'Jan', 'Nowak', '49151555824', 101),
(109, 'Pablo', 'Garcia', '49162555176', 101),
(110, 'Melanie', 'Dreschler', '49151555527', 103),
(111, 'Dieter', 'Durr', '49178555311', 103),
(112, 'Max', 'Mustermann', '49152555195', 104),
(113, 'Maxine', 'Mustermann', '49177555355', 104),
(114, 'Heiko', 'Fleischer', '49155555581', 105);
"""
pop_course = """
INSERT INTO course VALUES
(12, 'English for Logistics', 'ENG', 'A1', 10, '2020-02-01', TRUE, 1, 105),
(13, 'Beginner English', 'ENG', 'A2', 40, '2019-11-12', FALSE, 6, 101),
(14, 'Intermediate English', 'ENG', 'B2', 40, '2019-11-12', FALSE, 6, 101),
(15, 'Advanced English', 'ENG', 'C1', 40, '2019-11-12', FALSE, 6, 101),
(16, 'Mandarin für Autoindustrie', 'MAN', 'B1', 15, '2020-01-15', TRUE, 3, 103),
(17, 'Français intermédiaire', 'FRA', 'B1', 18, '2020-04-03', FALSE, 2, 101),
(18, 'Deutsch für Anfänger', 'DEU', 'A2', 8, '2020-02-14', TRUE, 4, 102),
(19, 'Intermediate English', 'ENG', 'B2', 10, '2020-03-29', FALSE, 1, 104),
(20, 'Fortgeschrittenes Russisch', 'RUS', 'C1', 4, '2020-04-08', FALSE, 5, 103);
"""
pop_takescourse = """
INSERT INTO takes_course VALUES
(101, 15),
(101, 17),
(102, 17),
(103, 18),
(104, 18),
(105, 18),
(106, 13),
(107, 13),
(108, 13),
(109, 14),
(109, 15),
(110, 16),
(110, 20),
(111, 16),
(114, 12),
(112, 19),
(113, 19);
"""
connection = create_db_connection("localhost", "root", pw, db)
execute_query(connection, pop_client)
execute_query(connection, pop_participant)
execute_query(connection, pop_course)
execute_query(connection, pop_takescourse)
Incrível! Agora criamos um banco de dados completo com relações, restrições e registros no MySQL, usando apenas comandos Python.
Nós passamos por este passo a passo para mantê-lo compreensível. Mas a essa altura você pode ver que tudo isso pode ser facilmente escrito em um script Python e executado em um comando no terminal. Coisas poderosas.
Ler dados
Agora temos um banco de dados funcional para trabalhar. Como analista de dados, é provável que você entre em contato com bancos de dados existentes nas organizações em que trabalha. Será muito útil saber como extrair dados desses bancos de dados para que possam ser alimentados em seu pipeline de dados python. É nisso que vamos trabalhar a seguir.
Para isso, precisaremos de mais uma função, desta vez usando cursor.fetchall() em vez de cursor.commit(). Com esta função, estamos lendo dados do banco de dados e não faremos nenhuma alteração.
def read_query(connection, query):
cursor = connection.cursor()
result = None
try:
cursor.execute(query)
result = cursor.fetchall()
return result
except Error as err:
print(f"Error: '{err}'")
Novamente, vamos implementar isso de uma maneira muito semelhante ao execute_query. Vamos experimentá-lo com uma consulta simples para ver como funciona.
q1 = """
SELECT *
FROM teacher;
"""
connection = create_db_connection("localhost", "root", pw, db)
results = read_query(connection, q1)
for result in results:
print(result)
Exatamente o que estamos esperando. A função também funciona com consultas mais complexas, como esta que envolve um JOIN nas tabelas de curso e cliente.
q5 = """
SELECT course.course_id, course.course_name, course.language, client.client_name, client.address
FROM course
JOIN client
ON course.client = client.client_id
WHERE course.in_school = FALSE;
"""
connection = create_db_connection("localhost", "root", pw, db)
results = read_query(connection, q5)
for result in results:
print(result)
Muito legal.
Para nossos pipelines de dados e fluxos de trabalho em Python, podemos querer obter esses resultados em formatos diferentes para torná-los mais úteis ou prontos para manipulação.
Vamos ver alguns exemplos para ver como podemos fazer isso.
Formatando a saída em uma lista
#Initialise empty list
from_db = []
# Loop over the results and append them into our list
# Returns a list of tuples
for result in results:
result = result
from_db.append(result)
Formatando a saída em uma lista de listas
# Returns a list of lists
from_db = []
for result in results:
result = list(result)
from_db.append(result)
Formatando a saída em um DataFrame pandas
Para analistas de dados que usam Python, o pandas é nosso velho amigo bonito e confiável. É muito simples converter a saída do nosso banco de dados em um DataFrame, e a partir daí as possibilidades são infinitas!
# Returns a list of lists and then creates a pandas DataFrame
from_db = []
for result in results:
result = list(result)
from_db.append(result)
columns = ["course_id", "course_name", "language", "client_name", "address"]
df = pd.DataFrame(from_db, columns=columns)
Espero que você possa ver as possibilidades se desdobrando na sua frente aqui. Com apenas algumas linhas de código, podemos extrair facilmente todos os dados que podemos manipular dos bancos de dados relacionais em que eles residem e puxá-los para nossos pipelines de análise de dados de última geração. Isso é algo realmente útil.
Atualizando registros
Quando estamos mantendo um banco de dados, às vezes precisaremos fazer alterações nos registros existentes. Nesta seção, veremos como fazer isso.
Digamos que o ILS seja notificado de que um de seus clientes existentes, a Big Business Federation, está mudando de escritório para 23 Fingiertweg, 14534 Berlin. Nesse caso, o administrador do banco de dados (somos nós!) precisará fazer algumas alterações.
Felizmente, podemos fazer isso com nossa função execute_query junto com a instrução SQL UPDATE.
update = """
UPDATE client
SET address = '23 Fingiertweg, 14534 Berlin'
WHERE client_id = 101;
"""
connection = create_db_connection("localhost", "root", pw, db)
execute_query(connection, update)
Observe que a cláusula WHERE é muito importante aqui. Se executarmos essa consulta sem a cláusula WHERE, todos os endereços de todos os registros em nossa tabela Client serão atualizados para 23 Fingiertweg. Isso não é muito o que estamos procurando fazer.
Observe também que usamos "WHERE client_id =101" na consulta UPDATE. Também seria possível usar "WHERE client_name ='Big Business Federation'" ou "WHERE address ='123 Falschungstraße, 10999 Berlin'" ou mesmo "WHERE address LIKE '%Falschung%'".
O importante é que a cláusula WHERE nos permite identificar exclusivamente o registro (ou registros) que queremos atualizar.
Excluindo registros
Também é possível usar nossa função execute_query para excluir registros, usando DELETE.
Ao usar SQL com bancos de dados relacionais, precisamos ter cuidado ao usar o operador DELETE. Este não é o Windows, não há 'Tem certeza de que deseja excluir isso?' pop-up de aviso e não há lixeira de reciclagem. Uma vez que excluímos algo, ele realmente se foi.
Com isso dito, nós realmente precisamos deletar coisas às vezes. Então, vamos dar uma olhada excluindo um curso da nossa tabela Curso.
Antes de mais nada, vamos nos lembrar dos cursos que temos.
Digamos que o curso 20, 'Fortgeschrittenes Russisch' (que é 'Russo avançado' para você e para mim), está chegando ao fim, então precisamos removê-lo do nosso banco de dados.
A essa altura, você não ficará surpreso com a forma como fazemos isso - salve o comando SQL como uma string e, em seguida, insira-o em nossa função execute_query.
delete_course = """
DELETE FROM course
WHERE course_id = 20;
"""
connection = create_db_connection("localhost", "root", pw, db)
execute_query(connection, delete_course)
Vamos verificar para confirmar que teve o efeito pretendido:
'Russo avançado' se foi, como esperávamos.
Isso também funciona com a exclusão de colunas inteiras usando DROP COLUMN e tabelas inteiras usando comandos DROP TABLE, mas não abordaremos isso neste tutorial.
No entanto, vá em frente e experimente com eles - não importa se você excluir uma coluna ou tabela de um banco de dados para uma escola fictícia, e é uma boa ideia se familiarizar com esses comandos antes de passar para um ambiente de produção.
Oh CRUD
A essa altura, já podemos concluir as quatro operações principais para armazenamento de dados persistentes.
Aprendemos a:
- Criar - bancos de dados, tabelas e registros totalmente novos
- Ler - extrair dados de um banco de dados e armazenar esses dados em vários formatos
- Atualizar - fazer alterações nos registros existentes no banco de dados
- Excluir - remover registros que não são mais necessários
Estas são coisas fantasticamente úteis para poder fazer.
Antes de terminarmos as coisas aqui, temos mais uma habilidade muito útil para aprender.
Criando registros a partir de listas
Vimos ao preencher nossas tabelas que podemos utilizar o comando SQL INSERT em nossa função execute_query para inserir registros em nosso banco de dados.
Dado que estamos usando Python para manipular nosso banco de dados SQL, seria útil poder pegar uma estrutura de dados Python (como uma lista) e inseri-la diretamente em nosso banco de dados.
Isso pode ser útil quando queremos armazenar logs de atividade do usuário em um aplicativo de mídia social que escrevemos em Python ou entradas de usuários em um Wiki que criamos, por exemplo. Há tantos usos possíveis para isso como você pode pensar.
Esse método também é mais seguro se nosso banco de dados estiver aberto para nossos usuários a qualquer momento, pois ajuda a prevenir ataques de SQL Injection, que podem danificar ou até destruir todo o nosso banco de dados.
Para fazer isso, escreveremos uma função usando o método executemany(), em vez do método execute() mais simples que usamos até agora.
def execute_list_query(connection, sql, val):
cursor = connection.cursor()
try:
cursor.executemany(sql, val)
connection.commit()
print("Query successful")
except Error as err:
print(f"Error: '{err}'")
Agora que temos a função, precisamos definir um comando SQL ('sql') e uma lista contendo os valores que desejamos inserir no banco de dados ('val'). Os valores devem ser armazenados como uma lista de tuplas, que é uma maneira bastante comum de armazenar dados em Python.
Para adicionar dois novos professores ao banco de dados, podemos escrever algum código como este:
sql = '''
INSERT INTO teacher (teacher_id, first_name, last_name, language_1, language_2, dob, tax_id, phone_no)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
'''
val = [
(7, 'Hank', 'Dodson', 'ENG', None, '1991-12-23', 11111, '+491772345678'),
(8, 'Sue', 'Perkins', 'MAN', 'ENG', '1976-02-02', 22222, '+491443456432')
]
Observe aqui que no código 'sql' usamos o '%s' como um espaço reservado para nosso valor. A semelhança com o espaço reservado '%s' para uma string em python é apenas coincidência (e francamente, muito confusa), queremos usar '%s' para todos os tipos de dados (strings, ints, datas, etc) com o MySQL Python Conector.
Você pode ver várias perguntas no Stackoverflow em que alguém ficou confuso e tentou usar espaços reservados '%d' para números inteiros porque está acostumado a fazer isso em Python. Isso não funcionará aqui - precisamos usar um '%s' para cada coluna à qual queremos adicionar um valor.
A função executemany então pega cada tupla em nossa lista 'val' e insere o valor relevante para aquela coluna no lugar do espaço reservado e executa o comando SQL para cada tupla contida na lista.
Isso pode ser feito para várias linhas de dados, desde que sejam formatadas corretamente. Em nosso exemplo, adicionaremos apenas dois novos professores, para fins ilustrativos, mas em princípio podemos adicionar quantos quisermos.
Vamos executar esta consulta e adicionar os professores ao nosso banco de dados.
connection = create_db_connection("localhost", "root", pw, db)
execute_list_query(connection, sql, val)
Bem-vindo ao ILS, Hank e Sue!
Esta é mais uma função profundamente útil, permitindo-nos pegar dados gerados em nossos scripts e aplicativos Python e inseri-los diretamente em nosso banco de dados.
Conclusão
Nós cobrimos muito terreno neste tutorial.
We have learned how to use Python and MySQL Connector to create an entirely new database in MySQL Server, create tables within that database, define the relationships between those tables, and populate them with data.
We have covered how to Create, Read, Update and Delete data in our database.
We have looked at how to extract data from existing databases and load them into pandas DataFrames, ready for analysis and further work taking advantage of all the possibilities offered by the PyData stack.
Going in the other direction, we have also learned how to take data generated by our Python scripts and applications, and write those into a database where they can be safely stored for later retrieval and manipulation.
I hope this tutorial has helped you to see how we can use Python and SQL together to be able to manipulate data even more effectively!
If you'd like to see more of my projects and work, please visit my website at craigdoesdata.de. If you have any feedback on this tutorial, please contact me directly - all feedback is warmly received!