MySQL Select em Python
Aprenda a usar SELECT em Python com mysql-connector-python: buscar todas as linhas, uma linha, colunas específicas e usar fetchone vs fetchall.
A instrução SELECT é a base de toda operação de leitura em banco de dados. Em Python você a executa por meio de um objeto cursor fornecido pelo mysql-connector-python e depois recupera os resultados com fetchall(), fetchone() ou fetchmany(). Este capítulo abrange os três métodos de busca, como selecionar colunas específicas, como trabalhar com nomes de colunas e os padrões de tratamento de erros que você precisa em código de produção.
Pré-requisitos
Instale o conector MySQL caso ainda não tenha feito isso:
pip install mysql-connector-pythonTodos os exemplos assumem:
- Um servidor MySQL em execução (local ou remoto).
- Um banco de dados chamado
mydatabasecom uma tabelacustomersque possui pelo menos as colunasid,nameeaddress.
Siga Python MySQL Create Table para criar a tabela e Python MySQL Insert para preenchê-la com linhas de exemplo antes de executar os exemplos de SELECT abaixo.
Conectando ao banco de dados
Cada exemplo começa com um objeto de conexão. Em vez de repetir a configuração em cada trecho de código, mantenha-a em um único lugar e reutilize-a:
import mysql.connector
from mysql.connector import Error
connection = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)Substitua yourusername e yourpassword pelas suas credenciais reais. Consulte Python MySQL Get Started para saber como armazenar credenciais em variáveis de ambiente em vez de codificá-las diretamente.
Selecionando todas as linhas com fetchall()
fetchall() recupera todas as linhas retornadas pela consulta e as armazena em uma lista Python de tuplas. Use-o quando o conjunto de resultados for pequeno o suficiente para caber confortavelmente na memória.
Selecionar todos os registros da tabela customers
import mysql.connector
from mysql.connector import Error
try:
connection = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
cursor = connection.cursor()
cursor.execute("SELECT * FROM customers")
rows = cursor.fetchall()
for row in rows:
print(row)
except Error as e:
print(f"Error: {e}")
finally:
if cursor:
cursor.close()
if connection.is_connected():
connection.close()Cada row é uma tupla cujos valores correspondem às colunas da tabela na ordem em que aparecem na instrução CREATE TABLE. Para uma tabela customers com colunas (id, name, address) você veria uma saída semelhante a:
(1, 'John', '123 Main St')
(2, 'Susan', '456 Oak Ave')
(3, 'Maria', '789 Pine Rd')Por que envolver tudo em try/except/finally?
Se uma exceção for lançada entre a abertura da conexão e o seu fechamento, a conexão vaza — ela permanece aberta e consome recursos do servidor até que o servidor a encerre por tempo limite. O bloco finally garante que cursor.close() e connection.close() sejam sempre chamados, mesmo quando algo dá errado.
Selecionando uma única linha com fetchone()
Quando você precisa apenas da primeira linha correspondente — ou sabe que a consulta retorna exatamente um resultado — fetchone() é mais eficiente do que fetchall(). Ele retorna uma única tupla ou None se não houver resultados.
Recuperar uma linha da tabela customers
import mysql.connector
from mysql.connector import Error
try:
connection = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
cursor = connection.cursor()
cursor.execute("SELECT * FROM customers")
row = cursor.fetchone()
if row:
print("First customer:", row)
else:
print("No records found.")
except Error as e:
print(f"Error: {e}")
finally:
if cursor:
cursor.close()
if connection.is_connected():
connection.close()fetchone() avança o ponteiro interno do cursor. Chamá-lo novamente retorna a próxima linha. Isso o torna adequado para iterar pelos resultados uma linha por vez sem carregar todo o conjunto de resultados na memória.
Selecionando colunas específicas
Usar SELECT * retorna todas as colunas da tabela. Para tabelas grandes ou quando você precisa apenas de alguns campos, nomeie as colunas explicitamente. Isso reduz os dados transferidos pela rede e torna a intenção do seu código clara.
Selecionar apenas as colunas name e address
import mysql.connector
from mysql.connector import Error
try:
connection = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
cursor = connection.cursor()
cursor.execute("SELECT name, address FROM customers")
rows = cursor.fetchall()
for row in rows:
print(row)
except Error as e:
print(f"Error: {e}")
finally:
if cursor:
cursor.close()
if connection.is_connected():
connection.close()Saída (exemplo):
('John', '123 Main St')
('Susan', '456 Oak Ave')
('Maria', '789 Pine Rd')Buscando linhas em lotes com fetchmany()
fetchmany(size) recupera size linhas por vez. Use-o quando o conjunto de resultados for grande demais para fetchall(), mas você ainda queira processar as linhas em blocos em vez de uma a uma.
Processar resultados 10 linhas por vez
import mysql.connector
from mysql.connector import Error
try:
connection = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
cursor = connection.cursor()
cursor.execute("SELECT * FROM customers")
batch_size = 10
while True:
rows = cursor.fetchmany(batch_size)
if not rows:
break
for row in rows:
print(row)
except Error as e:
print(f"Error: {e}")
finally:
if cursor:
cursor.close()
if connection.is_connected():
connection.close()fetchmany() retorna uma lista vazia quando não há mais linhas, que é o que a verificação if not rows: break detecta.
Acessando colunas pelo nome com um cursor de dicionário
Por padrão, cada linha é uma tupla simples. Se você tiver muitas colunas, acessar row[4] em vez de row["email"] torna o código difícil de ler e falha silenciosamente quando a ordem das colunas muda. Passe dictionary=True ao construtor do cursor para obter cada linha como um dict em vez de uma tupla.
Usar um cursor de dicionário para acesso a colunas pelo nome
import mysql.connector
from mysql.connector import Error
try:
connection = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
# dictionary=True makes each row a dict
cursor = connection.cursor(dictionary=True)
cursor.execute("SELECT * FROM customers")
rows = cursor.fetchall()
for row in rows:
print(f"ID: {row['id']}, Name: {row['name']}, Address: {row['address']}")
except Error as e:
print(f"Error: {e}")
finally:
if cursor:
cursor.close()
if connection.is_connected():
connection.close()Saída:
ID: 1, Name: John, Address: 123 Main St
ID: 2, Name: Susan, Address: 456 Oak AveCursores de dicionário tornam o código autodocumentado e resistente à reordenação de colunas.
Filtrando linhas com WHERE
Para recuperar apenas as linhas que correspondem a uma condição, adicione uma cláusula WHERE. Sempre use consultas parametrizadas — nunca formate valores fornecidos pelo usuário diretamente na string SQL, pois isso abre a porta para ataques de injeção de SQL.
Recuperar clientes que moram em uma rua específica
import mysql.connector
from mysql.connector import Error
try:
connection = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
cursor = connection.cursor()
sql = "SELECT * FROM customers WHERE address = %s"
val = ("123 Main St",) # Always pass a tuple, even for a single value
cursor.execute(sql, val)
rows = cursor.fetchall()
for row in rows:
print(row)
except Error as e:
print(f"Error: {e}")
finally:
if cursor:
cursor.close()
if connection.is_connected():
connection.close()O marcador %s é preenchido pelo driver do conector, que escapa o valor com segurança. Consulte Python MySQL Where para um tratamento completo de filtragem, incluindo múltiplas condições com AND/OR.
Usando SELECT com ORDER BY e LIMIT
Combine SELECT com ORDER BY para ordenar resultados e LIMIT para limitar o número de linhas retornadas. Esse padrão é essencial para exibir os registros mais recentes ou implementar paginação.
Obter os 3 clientes com os IDs mais altos, ordenados do mais recente ao mais antigo
import mysql.connector
from mysql.connector import Error
try:
connection = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
cursor = connection.cursor()
cursor.execute("SELECT * FROM customers ORDER BY id DESC LIMIT 3")
rows = cursor.fetchall()
for row in rows:
print(row)
except Error as e:
print(f"Error: {e}")
finally:
if cursor:
cursor.close()
if connection.is_connected():
connection.close()Para um guia dedicado à ordenação, consulte Python MySQL Order By. Para paginação com OFFSET, consulte Python MySQL Limit.
Verificando os nomes das colunas com cursor.description
Após chamar execute(), o atributo description do cursor contém metadados sobre cada coluna no resultado — incluindo o nome da coluna. Isso é útil quando você precisa dos nomes das colunas de forma dinâmica (por exemplo, ao construir uma exportação CSV) sem codificá-los diretamente.
Imprimir nomes de colunas junto com os dados
import mysql.connector
from mysql.connector import Error
try:
connection = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
cursor = connection.cursor()
cursor.execute("SELECT * FROM customers")
# cursor.description is a list of 7-item sequences; index 0 is the column name
column_names = [desc[0] for desc in cursor.description]
print("Columns:", column_names)
rows = cursor.fetchall()
for row in rows:
print(dict(zip(column_names, row)))
except Error as e:
print(f"Error: {e}")
finally:
if cursor:
cursor.close()
if connection.is_connected():
connection.close()Saída (exemplo):
Columns: ['id', 'name', 'address']
{'id': 1, 'name': 'John', 'address': '123 Main St'}
{'id': 2, 'name': 'Susan', 'address': '456 Oak Ave'}Escolhendo entre fetchall(), fetchone() e fetchmany()
| Método | Retorna | Melhor para |
|---|---|---|
fetchall() | Lista de todas as tuplas | Conjuntos de resultados pequenos a médios onde todas as linhas são necessárias de uma vez |
fetchone() | Tupla única ou None | Busca por chave primária; iteração linha a linha |
fetchmany(n) | Lista de até n tuplas | Conjuntos de resultados grandes processados em blocos de streaming |
Se você chamar fetchall() em um conjunto de resultados de um milhão de linhas, Python armazenará todas as um milhão de tuplas na memória ao mesmo tempo. Para tabelas grandes, use fetchmany() ou adicione uma cláusula LIMIT à consulta.
Erros comuns e como corrigi-los
| Erro | Causa provável | Correção |
|---|---|---|
mysql.connector.errors.ProgrammingError: Table doesn't exist | O nome da tabela está errado ou o banco de dados não foi selecionado | Verifique o nome da tabela; certifique-se de que o parâmetro database está definido em connect() |
mysql.connector.errors.InterfaceError: No result set | Chamar fetchall() após uma instrução que não é SELECT | Chame métodos de busca somente após SELECT, SHOW ou outras instruções que produzem resultados |
mysql.connector.errors.DatabaseError: Lost connection | Tempo limite de rede ou reinicialização do servidor | Restabeleça a conexão; para aplicações de longa duração, use um pool de conexões |
InternalError: Unread result found | Iniciar um novo execute() antes de consumir os resultados anteriores | Chame fetchall() ou cursor.reset() para esvaziar o conjunto de resultados anterior primeiro |
Resumo
- Execute uma instrução
SELECTcomcursor.execute("SELECT ..."). - Use
fetchall()para conjuntos de resultados pequenos,fetchone()para uma única linha efetchmany(n)para grandes conjuntos de dados processados em blocos. - Passe
dictionary=Trueao cursor para acessar colunas pelo nome em vez do índice. - Sempre use marcadores parametrizados
%sao filtrar com valores fornecidos pelo usuário. - Envolva toda operação de banco de dados em
try/except/finallypara garantir que a conexão seja fechada em caso de erro.
Capítulos relacionados
- Python MySQL Get Started — instale o driver e estabeleça uma conexão
- Python MySQL Create Table — defina o esquema da tabela para suas consultas
- Python MySQL Insert — adicione linhas antes de consultá-las
- Python MySQL Where — filtre resultados SELECT com condições
- Python MySQL Order By — ordene resultados SELECT
- Python MySQL Limit — restrinja o número de linhas retornadas
- Python MySQL Join — combine dados de múltiplas tabelas