Banco de Dados Relacionais com Python e SQLite
Neste artigo, vamos abordar os conceitos fundamentais de bancos de dados relacionais e como podemos interagir com eles usando a Python DB API. Este conteúdo é essencial para qualquer programador que deseja trabalhar com bancos de dados, principalmente em aplicações desenvolvidas em Python.
1. Introdução aos Bancos de Dados
O que é um Banco de Dados?
Os bancos de dados são coleções organizadas de dados, geralmente armazenados e acessados eletronicamente a partir de um sistema de computador. Eles são essenciais para armazenar, gerenciar e recuperar informações de forma eficiente e segura.
Tipos de Bancos de Dados
Existem vários tipos de bancos de dados, incluindo:
- Relacionais: Organizam os dados em tabelas.
- Não Relacionais: Incluem bancos de dados de documentos, chave-valor, colunares e gráficos.
- Orientados a Objetos: Armazenam dados na forma de objetos.
O tipo mais comum é o banco de dados relacional, que utiliza tabelas para organizar os dados.
O Papel do SGBD
Os Sistemas de Gerenciamento de Banco de Dados (SGBD) são softwares que interagem com o usuário, outras aplicações e o próprio banco de dados para capturar e analisar os dados. Exemplos populares incluem MySQL, PostgreSQL, SQLite, Oracle Database, Microsoft SQL Server e MariaDB.
2. Introdução aos Bancos de Dados Relacionais
Estrutura das Tabelas
Um banco de dados relacional organiza os dados em tabelas, cada uma composta de linhas (registros) e colunas (campos). Por exemplo, uma tabela 'Clientes' pode ter os campos 'ID', 'nome', 'email' e 'telefone'.
Chaves Primárias e Estrangeiras
- Chave Primária: Uma coluna (ou conjunto de colunas) cujo valor é único para cada registro, garantindo a identificação única dos registros.
- Chave Estrangeira: Um campo em uma tabela que corresponde à chave primária de outra tabela, estabelecendo relações entre as tabelas.
Relacionamentos entre Tabelas
Os bancos de dados relacionais permitem criar relações 'um para um', 'um para muitos' e 'muitos para muitos', facilitando consultas complexas que unem dados de várias tabelas.
3. SQL (Structured Query Language)
O SQL é a linguagem usada para interagir com bancos de dados relacionais. Com SQL, podemos:
- Criar tabelas
- Inserir, atualizar e deletar registros
- Executar consultas para buscar dados
4. Python DB API
Conectando-se a um Banco de Dados
A primeira etapa para trabalhar com um banco de dados em Python é estabelecer uma conexão usando a Python DB API. Por exemplo:
import sqlite3
conn = sqlite3.connect('example.db')
Inserindo Registros
Para inserir registros, usamos a operação INSERT
do SQL. Exemplo:
cursor = conn.cursor()
cursor.execute("INSERT INTO Clientes (nome, email) VALUES ('João', 'joao@example.com')")
conn.commit()
Atualizando Registros
A operação UPDATE
é usada para modificar registros existentes. Exemplo:
cursor.execute("UPDATE Clientes SET email = 'joao_novo@example.com' WHERE nome = 'João'")
conn.commit()
Deletando Registros
A operação DELETE
remove registros. Exemplo:
cursor.execute("DELETE FROM Clientes WHERE nome = 'João'")
conn.commit()
Operações em Lote
Para inserir muitos registros de uma vez, usamos o método executemany()
:
data = [('Maria', 'maria@example.com'), ('Carlos', 'carlos@example.com')]
cursor.executemany("INSERT INTO Clientes (nome, email) VALUES (?, ?)", data)
conn.commit()
Consultas com Resultados
- Único Resultado: Utilizamos o método
fetchone()
para recuperar um único registro.
cursor.execute("SELECT * FROM Clientes WHERE nome = 'Maria'")
result = cursor.fetchone()
- Múltiplos Resultados: Utilizamos o método
fetchall()
para recuperar todos os registros.
cursor.execute("SELECT * FROM Clientes")
results = cursor.fetchall()
Trabalhando com Resultados de Consulta
Os resultados são retornados como tuplas por padrão, mas podemos usar a classe sqlite3.Row
ou uma row_factory
customizada para melhor adequação.
5. Boas Práticas em Consultas SQL
Segurança e Eficiência
Ao escrever consultas SQL em Python, devemos:
- Evitar a concatenação de strings nas consultas
- Usar consultas parametrizadas para prevenir ataques de injeção SQL
Exemplo de Consulta Parametrizada
cursor.execute("SELECT * FROM Clientes WHERE nome = ?", ('Maria',))
6. Gerenciando Transações
A Python DB API permite gerenciar transações, o que é crucial para manter a integridade dos dados. Exemplo:
try:
conn.execute("BEGIN TRANSACTION")
cursor.execute("UPDATE Clientes SET email = 'maria_nova@example.com' WHERE nome = 'Maria'")
conn.commit()
except:
conn.rollback()
raise
Funções para manipular tabelas no SQLite.
Para adicionar comandos SQL importamos o módulo sqlite3
, e usamos a função cursor.execute()
.
Criar Banco de dados
import sqlite3
from pathlib import Path
ROOT_PATH = Path(__file__).parent
conexao = sqlite3.connect(ROOT_PATH / "teste_banco.sqlite")
cursor = conexao.cursor()
Criar tabela
def criar_tabela(conexao, cursor):
cursor.execute(
"CREATE TABLE clientes (id INTEGER PRIMARY KEY AUTOINCREMENT, nome VARCHAR(100), email VARCHAR(150))"
)
conexao.commit()
criar_tabela(conexao, cursor)
Inserir um registro
def inserir_registro(conexao, cursor, nome, email):
data = (nome, email)
cursor.execute("INSERT INTO clientes (nome, email) VALUES (?,?);", data)
conexao.commit()
inserir_registro(conexao, cursor, "João", "joao@gmail.com")
Atualizar um registro
def atualizar_registro(conexao, cursor, nome, email, id):
data = (nome, email, id)
cursor.execute("UPDATE clientes SET nome=?, email=? WHERE id=?;", data)
conexao.commit()
atualizar_registro(conexao, cursor, "João Atualizado", "joao.atualizado@gmail.com", 1)
Inserir vários registros
def inserir_varios(conexao, cursor, dados):
cursor.executemany("INSERT INTO clientes (nome, email) VALUES (?,?)", dados)
conexao.commit()
dados = [
("Guilherme", "guilherme@gmail.com"),
("Chappie", "chappie@gmail.com"),
("Melaine", "melaine@gmail.com"),
]
inserir_varios(conexao, cursor, dados)
Excluir um registro
def excluir_registro(conexao, cursor, id):
data = (id,)
cursor.execute("DELETE FROM clientes WHERE id=?;", data)
conexao.commit()
excluir_registro(conexao, cursor, 2)
Recuperar um registro
def recuperar_cliente(cursor, id):
cursor.execute("SELECT email, id, nome FROM clientes WHERE id=?", (id,))
return cursor.fetchone()
cliente = recuperar_cliente(cursor, 5)
print(cliente)
Recuperar um dicionário do registro
É necessário um novo cursor para converter a tupla em dicionário, para isso adicione:
cursor.row_factory = sqlite3.Row
def recuperar_cliente(cursor, id):
cursor.execute("SELECT email, id, nome FROM clientes WHERE id=?", (id,))
return cursor.fetchone()
cliente = recuperar_cliente(cursor, 5)
print(dict(cliente))
print(cliente["email"], cliente["id"], cliente["nome"])
print(f'Seja bem vindo ao sistema {cliente["nome"]}')
Listar os nomes do dicionário de registros
def listar_clientes(cursor):
return cursor.execute("SELECT * FROM clientes ORDER BY nome DESC;")
clientes = listar_clientes(cursor)
for cliente in clientes:
print(dict(cliente))
Conclusão
Compreender os conceitos de bancos de dados relacionais e saber como interagir com eles usando Python é essencial para o desenvolvimento de aplicações robustas e eficientes. Ao seguir boas práticas e usar as ferramentas adequadas, podemos garantir a segurança e a integridade dos nossos dados.
Este artigo cobriu os fundamentos e práticas básicas. À medida que você se aprofunda, explorará tópicos mais avançados e específicos para suas necessidades de desenvolvimento.
Esse conteúdo foi anotado da trilha Desenvolvedor Python.