Consultas parametrizadas
Evite injeção de SQL
Consultas parametrizadas é uma aula grátis de Python Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Python Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Python Academy inclui 4 aulas no total.
O perigo de criar cadeias de caracteres
Construir SQL concatenando cadeias de caracteres é arriscado. Se a entrada do usuário contiver SQL, ela poderá alterar sua consulta. Isso é chamado de injeção de SQL.
Nunca faça isso com dados não confiáveis.
name = 'Alice'
# Unsafe pattern - do NOT do this
query = "SELECT * FROM users WHERE name = '" + name + "'"
print(query)Como é uma tentativa de injeção
Imagine um valor malicioso. Concatená-lo altera completamente o significado da consulta.
name = "x' OR '1'='1"
query = "SELECT * FROM users WHERE name = '" + name + "'"
print(query)
print('The OR clause makes every row match!')Marcadores de posição ao resgate
A maneira segura é usar consultas parametrizadas. Use ? como marcador de posição e passe os valores como uma tupla. O controlador faz o escape deles com segurança.
import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)')
cur.execute('INSERT INTO users (name) VALUES (?)', ('Alice',))
cur.execute('SELECT * FROM users')
print(cur.fetchall())
conn.close()Vários marcadores de posição
Use um ? para cada valor. Passe-os em uma tupla na mesma ordem em que aparecem.
import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)')
cur.execute('INSERT INTO users (name, age) VALUES (?, ?)', ('Bob', 25))
cur.execute('SELECT * FROM users')
print(cur.fetchall())
conn.close()Tuplas de um único valor
Uma tupla de um elemento precisa de uma vírgula no final: ('Alice',). Sem ela, o Python trata os parênteses apenas como agrupamento.
good = ('Alice',)
bad = ('Alice')
print(type(good), type(bad))Tentativa de injeção bloqueada
Com marcadores de posição, um valor malicioso é tratado como dados comuns, não como SQL. Ele simplesmente não encontra correspondências.
import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)')
cur.execute('INSERT INTO users (name) VALUES (?)', ('Alice',))
evil = "x' OR '1'='1"
cur.execute('SELECT * FROM users WHERE name = ?', (evil,))
print('Rows matched:', cur.fetchall())
conn.close()Marcadores de posição nomeados
O SQLite também aceita marcadores de posição nomeados com a sintaxe :name. Passe um dicionário de valores.
import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)')
cur.execute('INSERT INTO users (name, age) VALUES (:n, :a)', {'n': 'Carol', 'a': 40})
cur.execute('SELECT * FROM users')
print(cur.fetchall())
conn.close()Parâmetros em WHERE
Os marcadores de posição funcionam em qualquer cláusula que aceite um valor, inclusive em WHERE.
import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)')
cur.execute('INSERT INTO users (name, age) VALUES (?, ?)', ('Alice', 30))
cur.execute('INSERT INTO users (name, age) VALUES (?, ?)', ('Bob', 25))
cur.execute('SELECT name FROM users WHERE age > ?', (28,))
print(cur.fetchall())
conn.close()executemany
Para inserir muitas linhas, use executemany() com uma lista de tuplas. Isso é mais rápido e continua sendo seguro.
import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)')
rows = [('Alice',), ('Bob',), ('Carol',)]
cur.executemany('INSERT INTO users (name) VALUES (?)', rows)
cur.execute('SELECT COUNT(*) FROM users')
print(cur.fetchone())
conn.close()Marcadores de posição não servem para identificadores
Os marcadores de posição funcionam apenas para valores, não para nomes de tabelas ou colunas. Esses nomes devem vir de uma lista de permissões confiável no seu próprio código.
import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)')
allowed = {'name', 'id'}
col = 'name'
if col in allowed:
cur.execute('SELECT ' + col + ' FROM users')
print('Safe column query ran')
conn.close()Uma função de inserção reutilizável
Encapsular inserções parametrizadas em uma função mantém seu código organizado e seguro de forma consistente.
import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)')
def add_user(cursor, name):
cursor.execute('INSERT INTO users (name) VALUES (?)', (name,))
add_user(cur, 'Dave')
cur.execute('SELECT * FROM users')
print(cur.fetchall())
conn.close()Verificação rápida
Teste seus conhecimentos sobre consultas seguras.
Recapitulação
Você aprendeu a escrever consultas protegidas contra injeção.
- Nunca concatene entradas não confiáveis ao SQL
- Use marcadores de posição
?com uma tupla de valores - Os marcadores de posição nomeados
:namerecebem um dicionário executemany()insere muitas linhas com segurança- Os marcadores de posição servem para valores, não para identificadores
Perguntas Frequentes
A aula “Consultas parametrizadas” é grátis?
Sim — o texto completo de “Consultas parametrizadas” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Python Academy, atualize para CoddyKit PRO. O curso de Python Academy inclui 4 aulas no total.
O que vou aprender em “Consultas parametrizadas”?
Evite injeção de SQL Você pratica Python Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Python Academy?
Nenhuma experiência prévia é necessária. Python Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Consultas parametrizadas”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Python Academy?
Sim. Cada aula de Python Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Conexão e criação de tabelas
- Inserir, selecionar, atualizar e excluir
- Consultas parametrizadas
- Transações e gerenciadores de contexto