【Cláusula BETWEEN do SQL】Domine as Buscas por Intervalo! Uma Forma Inteligente de Especificar Intervalos para Números e Datas
Em desenvolvimento web e de aplicações, é muito comum a necessidade de extrair dados que se enquadram em um determinado intervalo, como "produtos com preço entre R$100 e R$500" ou "usuários que se cadastraram entre 1 e 30 de junho".
Ao escrever tal condição em uma cláusula WHERE, como você faria?
WHERE price >= 1000 AND price <= 5000
Dessa forma, usando operadores de comparação (>=, <=) e AND, você pode, claro, especificar um intervalo. No entanto, o SQL fornece um comando dedicado para tornar essa "busca por intervalo" mais intuitiva e limpa. Esse é o nosso tópico principal de hoje: a cláusula BETWEEN.
Este artigo explicará detalhadamente tudo, desde o uso básico da cláusula BETWEEN, até sua aplicação com intervalos de datas, e sua forma negativa, NOT BETWEEN, tudo com código que você pode copiar e colar. Vamos abandonar as desajeitadas cadeias de operadores de comparação e adquirir a habilidade de escrever um SQL inteligente e fácil de ler para todos!
Preparação: Vamos Preparar Nossos Dados de Pedidos
Para experimentar as buscas por intervalo, primeiro precisamos de alguns dados para trabalhar. Desta vez, vamos criar uma tabela orders que imita o histórico de pedidos de um site de e-commerce. Ao incluir dados com vários preços e datas de pedido, será mais fácil perceber os efeitos da cláusula BETWEEN.
-- Se a tabela orders existir, exclua-a (para testes repetíveis)
DROP TABLE IF EXISTS orders;
-- Crie uma nova tabela orders
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
product_name TEXT NOT NULL,
price INTEGER NOT NULL,
order_date DATE NOT NULL,
quantity INTEGER NOT NULL
);
-- Insira dados iniciais
INSERT INTO orders (id, product_name, price, order_date, quantity) VALUES
(1, 'Caneta Esferográfica Incrível', 200, '2025-06-05', 3),
(2, 'Caderno Mágico', 500, '2025-06-10', 5),
(3, 'Panela de Arroz Definitiva', 30000, '2025-06-15', 1),
(4, 'Maçã Milagrosa', 980, '2025-06-20', 10),
(5, 'Hub USB-C', 4500, '2025-06-25', 2),
(6, 'Pincel Tradicional', 12000, '2025-06-30', 1),
(7, 'Chocolate Premium', 3500, '2025-07-01', 4);
Agora estamos prontos para extrair dados usando vários intervalos.
【O Básico】Especificando um Intervalo Numérico com a Cláusula BETWEEN
A sintaxe básica da cláusula BETWEEN é muito direta.
WHERE nome_da_coluna BETWEEN valor_mínimo AND valor_máximo;
O ponto mais importante aqui é que o intervalo para a cláusula `BETWEEN` é inclusivo, o que significa que inclui tanto o valor mínimo quanto o máximo especificados. Em outras palavras, WHERE price BETWEEN 1000 AND 5000 significa exatamente a mesma coisa que WHERE price >= 1000 AND price <= 5000. Certifique-se de lembrar deste ponto de que "inclui ambas as extremidades".
Cenário: "Encontrar todos os produtos com um preço entre 1.000 e 5.000."
SELECT * FROM orders
WHERE price BETWEEN 1000 AND 5000;
Resultado:
id | product_name | price | order_date | quantity
---|-------------------|-------|------------|----------
5 | Hub USB-C | 4500 | 2025-06-25 | 2
7 | Chocolate Premium | 3500 | 2025-07-01 | 4
O código é mais limpo do que usar dois operadores de comparação, e a intenção de "um intervalo de 1.000 a 5.000" é transmitida de forma mais direta, não acha?
【Aplicação】Especificando um Intervalo de Datas com a Cláusula BETWEEN
Uma característica conveniente da cláusula BETWEEN é que ela pode ser usada não apenas para números, mas também para especificar intervalos de datas (tipo DATE) e data e hora (tipo DATETIME). Como os requisitos para extrair dados de um período específico são muito comuns em aplicações web, esta é uma técnica de uso frequente.
Cenário: "Encontrar todos os pedidos feitos durante junho de 2025."
Neste caso, especificamos o início do intervalo como "2025-06-01" e o fim como "2025-06-30".
SELECT * FROM orders
WHERE order_date BETWEEN '2025-06-01' AND '2025-06-30';
Resultado:
id | product_name | price | order_date | quantity
---|-------------------------------|-------|------------|----------
1 | Caneta Esferográfica Incrível | 200 | 2025-06-05 | 3
2 | Caderno Mágico | 500 | 2025-06-10 | 5
3 | Panela de Arroz Definitiva | 30000 | 2025-06-15 | 1
4 | Maçã Milagrosa | 980 | 2025-06-20 | 10
5 | Hub USB-C | 4500 | 2025-06-25 | 2
6 | Pincel Tradicional | 12000 | 2025-06-30 | 1
Como você pode ver, os pedidos de 1º de junho e 30 de junho estão devidamente incluídos no resultado. Isso também se deve à natureza "inclusiva de ambas as extremidades" da cláusula BETWEEN.
【A Condição Oposta】Especificando o que está Fora de um Intervalo com NOT BETWEEN
Se você quiser encontrar coisas que estão **fora** de um intervalo especificado, use a cláusula NOT BETWEEN.
Há um ponto a ter em atenção aqui. Enquanto price BETWEEN 1000 AND 5000 significava "maior ou igual a 1000 E menor ou igual a 5000", price NOT BETWEEN 1000 AND 5000 significa "menor que 1000 **OU** maior que 5000" (price < 1000 OR price > 5000). Em outras palavras, os próprios valores-limite não são incluídos no resultado.
Cenário: "Encontrar todos os produtos que são ou muito baratos (abaixo de 1.000) ou muito caros (acima de 5.000)."
SELECT * FROM orders
WHERE price NOT BETWEEN 1000 AND 5000;
Resultado:
id | product_name | price | order_date | quantity
---|-------------------------------|-------|------------|----------
1 | Caneta Esferográfica Incrível | 200 | 2025-06-05 | 3
2 | Caderno Mágico | 500 | 2025-06-10 | 5
3 | Panela de Arroz Definitiva | 30000 | 2025-06-15 | 1
4 | Maçã Milagrosa | 980 | 2025-06-20 | 10
6 | Pincel Tradicional | 12000 | 2025-06-30 | 1
Embora nossos dados de amostra não tenham produtos com preço exato de 1.000 ou 5.000, lembre-se de que, mesmo que existissem, eles não seriam incluídos neste resultado.
【Playground Interativo】Domine as Buscas por Intervalo Executando SQL no seu Navegador!
Agora, é hora de transformar conhecimento em habilidade! Copie todo o código HTML abaixo, salve-o como um arquivo tipo sql_between_test.html e abra-o no seu navegador. Seu próprio ambiente SQL pessoal será iniciado, pré-carregado com a tabela orders que usamos neste artigo.
Tente alterar os intervalos numéricos ou de datas para se familiarizar com a natureza "inclusiva de ambas as extremidades" da cláusula BETWEEN. Experimente também o NOT BETWEEN e veja como os resultados mudam!
<!DOCTYPE html>
<html lang="pt">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Playground Online da Cláusula BETWEEN do SQL</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; line-height: 1.7; color: #333; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
h1 { color: #16a085; }
textarea { width: 100%; height: 180px; font-family: "SF Mono", "Consolas", monospace; font-size: 16px; padding: 12px; border: 1px solid #ccc; border-radius: 6px; box-sizing: border-box; margin-bottom: 1rem; }
button { background-color: #1abc9c; color: white; border: none; padding: 12px 22px; font-size: 16px; border-radius: 6px; cursor: pointer; transition: background-color 0.2s; }
button:hover { background-color: #16a085; }
button:disabled { background-color: #bdc3c7; cursor: not-allowed; }
#result-container { margin-top: 2rem; border: 1px solid #ddd; padding: 1rem; border-radius: 6px; background: #fdfdfd; min-height: 50px; }
#error-message { color: #e74c3c; font-weight: bold; }
table { border-collapse: collapse; width: 100%; margin-top: 1rem; }
th, td { border: 1px solid #ddd; padding: 10px; text-align: left; }
th { background-color: #f2f2f2; }
tr:nth-child(even) { background-color: #f9f9f9; }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/sql-wasm.js"></script>
</head>
<body>
<h1>Vamos Experimentar o SQL!</h1>
<p>Digite uma instrução SQL na área de texto abaixo e clique no botão "Executar". Experimente com diferentes intervalos!</p>
<textarea id="sql-input">-- Encontrar pedidos feitos entre 10 e 25 de junho
SELECT * FROM orders
WHERE order_date BETWEEN '2025-06-10' AND '2025-06-25';
</textarea>
<button id="execute-btn">Executar</button>
<div id="result-container">
<p id="error-message"></p>
<div id="result-output"></div>
</div>
<script>
const sqlInput = document.getElementById('sql-input');
const executeBtn = document.getElementById('execute-btn');
const errorMsg = document.getElementById('error-message');
const resultOutput = document.getElementById('result-output');
let db;
async function initDb() {
executeBtn.disabled = true;
executeBtn.textContent = 'Inicializando BD...';
try {
const SQL = await initSqlJs({
locateFile: file => `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/${file}`
});
db = new SQL.Database();
const setupSql = `
DROP TABLE IF EXISTS orders;
CREATE TABLE orders (id INTEGER PRIMARY KEY, product_name TEXT NOT NULL, price INTEGER NOT NULL, order_date DATE NOT NULL, quantity INTEGER NOT NULL);
INSERT INTO orders (id, product_name, price, order_date, quantity) VALUES
(1, 'Caneta Esferográfica Incrível', 200, '2025-06-05', 3),
(2, 'Caderno Mágico', 500, '2025-06-10', 5),
(3, 'Panela de Arroz Definitiva', 30000, '2025-06-15', 1),
(4, 'Maçã Milagrosa', 980, '2025-06-20', 10),
(5, 'Hub USB-C', 4500, '2025-06-25', 2),
(6, 'Pincel Tradicional', 12000, '2025-06-30', 1),
(7, 'Chocolate Premium', 3500, '2025-07-01', 4);
`;
db.run(setupSql);
executeBtn.disabled = false;
executeBtn.textContent = 'Executar';
resultOutput.innerHTML = '<p>Pronto! Sinta-se à vontade para experimentar suas próprias consultas SQL.</p>';
} catch (err) {
errorMsg.textContent = 'Falha ao inicializar o banco de dados: ' + err.message;
console.error(err);
}
}
function executeSql() {
if (!db) return;
const sql = sqlInput.value;
errorMsg.textContent = '';
resultOutput.innerHTML = '';
try {
const results = db.exec(sql);
if (results.length === 0) {
resultOutput.innerHTML = '<p>Consulta executada com sucesso, mas nenhum conjunto de resultados foi retornado.</p>';
return;
}
results.forEach(result => {
const table = document.createElement('table');
const thead = document.createElement('thead');
const tbody = document.createElement('tbody');
const headerRow = document.createElement('tr');
result.columns.forEach(colName => {
const th = document.createElement('th');
th.textContent = colName;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
result.values.forEach(row => {
const bodyRow = document.createElement('tr');
row.forEach(cellValue => {
const td = document.createElement('td');
td.textContent = cellValue === null ? 'NULL' : cellValue;
bodyRow.appendChild(td);
});
tbody.appendChild(bodyRow);
});
table.appendChild(thead);
table.appendChild(tbody);
resultOutput.appendChild(table);
});
} catch (err) {
errorMsg.textContent = 'Erro de SQL: ' + err.message;
console.error(err);
}
}
executeBtn.addEventListener('click', executeSql);
initDb();
</script>
</body>
</html>
Pontos a Observar: Manipulação de Data e Hora e Ordem dos Valores
Embora a cláusula BETWEEN seja simples e poderosa, há alguns pontos a serem observados.
- Ordem dos Valores: Ao escrever
BETWEEN A AND B, você deve sempre especificar o valor menor para A e o valor maior para B. Se você inverter a ordem, comoBETWEEN 5000 AND 1000, não corresponderá a nenhum registro, mesmo que existam dados nesse intervalo. Certifique-se sempre de escrever na ordem de "valor mínimo E valor máximo". - Manipulação de Data e Hora (tipo TIMESTAMP, etc.): Você precisa ter um cuidado especial ao usar
BETWEENcom colunas que incluem a hora (por exemplo, `YYYY-MM-DD HH:MM:SS`). Por exemplo, se você especificarorder_datetime BETWEEN '2025-06-01' AND '2025-06-30', isso é interpretado internamente como sendo até `'2025-06-30 00:00:00'`. Como resultado, um pedido feito na tarde de 30 de junho (por exemplo, '2025-06-30 15:00:00') estaria fora do intervalo e não seria incluído nos resultados. Se você quiser incluir todo o dia 30 de junho, a maneira confiável é especificar a hora explicitamente, comoBETWEEN '2025-06-01 00:00:00' AND '2025-06-30 23:59:59', ou usar operadores de comparação para especificar "antes do início do dia seguinte", comoorder_datetime >= '2025-06-01' AND order_datetime < '2025-07-01'.
Conclusão
Neste artigo, aprendemos sobre a cláusula BETWEEN, que permite buscas por intervalo de números e datas de forma intuitiva.
- Sintaxe Básica:
WHERE nome_da_coluna BETWEEN valor_mínimo AND valor_máximo. É mais legível do que usar operadores de comparação (>= ... AND <= ...). - O Intervalo é Inclusivo: Este é o ponto mais importante—a cláusula
BETWEENé avaliada como "maior ou igual a E menor ou igual a". - `NOT BETWEEN`: Extrai dados fora do intervalo. Este é avaliado como "menor que OU maior que" e não inclui os valores-limite.
- Também para Datas: Ao especificar strings no formato
'YYYY-MM-DD', você pode facilmente realizar buscas por intervalo de datas. - Considerações Chave: Sempre escreva na ordem de "mínimo E máximo" e esteja ciente de que é necessário um cuidado especial para especificar intervalos para colunas que incluem a hora.
Ao dominar a cláusula BETWEEN, o SQL que você escreve se tornará mais simples e sua intenção mais clara. Dê um passo além das simples combinações de operadores de comparação e adicione uma técnica de extração de dados mais refinada à sua caixa de ferramentas!