W3docs

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-python

Todos os exemplos assumem:

  • Um servidor MySQL em execução (local ou remoto).
  • Um banco de dados chamado mydatabase com uma tabela customers que possui pelo menos as colunas id, name e address.

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 Ave

Cursores 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étodoRetornaMelhor para
fetchall()Lista de todas as tuplasConjuntos de resultados pequenos a médios onde todas as linhas são necessárias de uma vez
fetchone()Tupla única ou NoneBusca por chave primária; iteração linha a linha
fetchmany(n)Lista de até n tuplasConjuntos 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

ErroCausa provávelCorreção
mysql.connector.errors.ProgrammingError: Table doesn't existO nome da tabela está errado ou o banco de dados não foi selecionadoVerifique o nome da tabela; certifique-se de que o parâmetro database está definido em connect()
mysql.connector.errors.InterfaceError: No result setChamar fetchall() após uma instrução que não é SELECTChame métodos de busca somente após SELECT, SHOW ou outras instruções que produzem resultados
mysql.connector.errors.DatabaseError: Lost connectionTempo limite de rede ou reinicialização do servidorRestabeleça a conexão; para aplicações de longa duração, use um pool de conexões
InternalError: Unread result foundIniciar um novo execute() antes de consumir os resultados anterioresChame fetchall() ou cursor.reset() para esvaziar o conjunto de resultados anterior primeiro

Resumo

  • Execute uma instrução SELECT com cursor.execute("SELECT ...").
  • Use fetchall() para conjuntos de resultados pequenos, fetchone() para uma única linha e fetchmany(n) para grandes conjuntos de dados processados em blocos.
  • Passe dictionary=True ao cursor para acessar colunas pelo nome em vez do índice.
  • Sempre use marcadores parametrizados %s ao filtrar com valores fornecidos pelo usuário.
  • Envolva toda operação de banco de dados em try/except/finally para garantir que a conexão seja fechada em caso de erro.

Capítulos relacionados

Was this page helpful?