Curso de Python / Gravar dados no SQLite com parâmetros e transações
O módulo sqlite3 grava dados SQL em um arquivo sem exigir um servidor de banco de dados separado. Passe os valores como parâmetros e defina claramente quando confirmar, reverter e encerrar uma conexão.
Definir a política de transações
SQLite é um mecanismo de banco de dados incorporado ao programa. Um arquivo local é conveniente para esta prática, mas as condições de concorrência e operação são diferentes das de um banco com servidor próprio. Abrir uma conexão não significa que todas as alterações seguintes já estejam confirmadas no arquivo.
O exemplo exige Python 3.12 ou posterior porque usa autocommit=False explicitamente. Esse parâmetro fixa a política de controle de transações, em vez de depender do comportamento padrão da instalação. Dentro de with con:, uma saída normal confirma a transação com commit; uma exceção provoca rollback, revertendo o trabalho da transação.
O bloco with con não fecha a conexão. O finally faz isso separadamente com con.close(). Essa divisão entre tratamento de sucesso, falha e limpeza também aparece na aula de exceções com try e finally. Consulte o controle de transações do módulo sqlite3.
Inserir, atualizar e consultar um registro
Crie uma pasta de prática nova para que ledger-demo.db seja um banco descartável deste exercício. Salve o código completo como sqlite_demo.py, em UTF-8, e execute python sqlite_demo.py no terminal do ambiente virtual selecionado. No macOS ou Ubuntu, fora de um ambiente virtual, use python3 se esse for o comando do interpretador. O módulo costuma acompanhar as distribuições de CPython; se não estiver disponível, consulte a documentação da distribuição usada.
import sqlite3
MAX_AMOUNT = 1_000_000_000_000
amount = 8000
if type(amount) is not int or not 0 <= amount <= MAX_AMOUNT:
raise ValueError("amount outside practice range")
con = sqlite3.connect("ledger-demo.db", autocommit=False)
try:
with con:
con.execute("CREATE TABLE IF NOT EXISTS expenses (id TEXT PRIMARY KEY, name TEXT NOT NULL, amount INTEGER NOT NULL CHECK(amount BETWEEN 0 AND 1000000000000))")
con.execute("INSERT INTO expenses VALUES (?, ?, ?) ON CONFLICT(id) DO UPDATE SET name=excluded.name, amount=excluded.amount", ("e1", "lunch", amount))
print(con.execute("SELECT name, amount FROM expenses ORDER BY id").fetchall())
finally:
con.close()
Resultado esperado:
[('lunch', 8000)]
O arquivo do banco fica na pasta atual do terminal. O programa cria a tabela expenses se ela não existir, grava a despesa com identificador e1 e consulta nome e quantia em ordem de identificador. fetchall() devolve uma lista de tuplas, razão do formato exibido.
A cláusula ON CONFLICT(id) DO UPDATE atualiza o nome e a quantia quando já existe uma linha com o mesmo identificador. Por isso, executar novamente não acrescenta outra cópia de e1. Essa política é uma atualização da mesma identidade; para registrar outra despesa, use outro identificador.
Distinguir valores, estrutura SQL e restrições
Os três pontos de interrogação são posições de valores. O segundo argumento de execute fornece a tupla correspondente, sem concatenar os dados à instrução SQL. Para apenas um valor, a tupla precisa de vírgula, como (value,). Aspas ou fragmentos de SQL dentro de um nome devem continuar sendo dados, não comandos executados.
Parâmetros de valores não substituem nomes de tabelas, colunas ou regras de ordenação. Se a aplicação permitir escolher uma coluna, selecione a estrutura a partir de uma lista explícita de opções aceitas; não concatene diretamente uma expressão recebida do usuário.
PRIMARY KEY identifica o registro; NOT NULL impede a ausência de nome e valor; CHECK aplica o intervalo à quantia. A validação Python exige um inteiro, exclui booleanos e aceita de zero a 1.000.000.000.000, inclusive. É um limite didático da aplicação, não o maior inteiro possível de SQLite.
Inteiros Python podem crescer dentro dos limites de memória, mas a classe de armazenamento INTEGER do SQLite representa inteiros com sinal de até 64 bits. Além disso, declarar uma coluna INTEGER nesta tabela comum não impõe sozinho uma tipagem estrita: SQLite usa afinidade de tipos. Um valor real dentro do intervalo pode passar pelo CHECK se outro caminho de escrita ignorar a validação Python. Se todos os gravadores precisarem garantir inteiros, projete restrições adicionais ou um esquema adequado à exigência. Veja os tipos e classes de armazenamento do SQLite.
CREATE TABLE IF NOT EXISTS não atualiza as restrições de uma tabela já existente. Por isso, comece com a pasta nova indicada. Alterar um banco de trabalho exige backup e uma migração planejada; não acrescente DROP TABLE apenas para fazer o exemplo rodar novamente.
Testar rejeição, repetição e persistência
- Execute o programa duas vezes na mesma pasta. A saída deve continuar com uma única linha lunch 8000, pois o identificador não mudou.
- Troque apenas
amount = 8000poramount = -1. O programa deve gerarValueErrorantes de abrir o banco. Restaure o valor e execute novamente; a despesa anterior permanece disponível. - Experimente uma quantia válida diferente, como 9000. O mesmo identificador deve ser atualizado, sem aumentar o número de linhas. Restaure 8000 para recuperar a saída inicial.
- Depois, troque somente o identificador e1 por e2 para acrescentar outro registro. A consulta deve retornar duas linhas em ordem de identificador; ela mostra apenas nome e valor, então duas despesas iguais podem aparecer como tuplas idênticas. Se precisar distinguir visualmente os identificadores, inclua
idna lista do SELECT durante a investigação.
Uma transação permite confirmar ou reverter um conjunto de escritas. Por exemplo, uma atualização válida seguida de uma escrita que viola CHECK deve ser revertida em conjunto se a exceção sair do mesmo with con. Fechar uma conexão é outra responsabilidade e não substitui a definição do commit.
Não presuma a ordem de um SELECT sem ORDER BY. Se ocorrer database is locked, investigue outras conexões, transações longas e arquivos ainda em uso antes de repetir gravações. Para repetir os testes com uma única despesa sem apagar dados anteriores, use outra pasta descartável.




