Referência

Referência SQL

Comandos, sintaxe e notas breves — do SELECT às funções de janela, índices e transações. Abra um artigo para se aprofundar.

Básico: SELECT e filtragem4

SELECT … FROM
Artigo
SELECT col1, col2 FROM table_name;

Escolha colunas de uma tabela.

Veja também:····
WHERE
Artigo
SELECT * FROM t
WHERE col = 5 AND status = 'active';

Filtra linhas: =, <>, <, >, AND, OR, IN, BETWEEN, LIKE.

Veja também:····
ORDER BY
Artigo
SELECT * FROM t ORDER BY created_at DESC;

Ordena o resultado. ASC crescente (padrão), DESC decrescente.

Veja também:····
LIMIT
Artigo
SELECT * FROM t ORDER BY id LIMIT 10;

Limita o número de linhas retornadas.

Veja também:····

Junção de tabelas (JOIN)7

INNER JOIN
Artigo
SELECT * FROM a JOIN b ON a.id = b.a_id;

Apenas as linhas que têm correspondência em ambas as tabelas.

Veja também:·····
LEFT JOIN
Artigo
SELECT * FROM a LEFT JOIN b ON a.id = b.a_id;

Todas as linhas da tabela à esquerda; NULL à direita se não houver correspondência.

Veja também:·····
Aliases
Artigo
SELECT u.name
FROM users u
JOIN orders o ON o.user_id = u.id;

Nomes curtos para as tabelas — obrigatórios quando as colunas têm o mesmo nome.

Veja também:····
CROSS JOIN
Artigo
SELECT * FROM sizes CROSS JOIN colors;

Produto cartesiano — cada linha à esquerda com cada linha à direita. Para gerar todas as combinações.

Veja também:·····
FULL OUTER JOIN
Artigo
SELECT * FROM a FULL OUTER JOIN b ON a.id = b.a_id;

Todas as linhas de ambas as tabelas; NULL onde não há correspondência. O MySQL não tem FULL JOIN — emule com LEFT ∪ RIGHT.

Veja também:·····
Self-join
Artigo
SELECT e.name, m.name AS manager
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;

Uma tabela unida a si mesma via alias — para hierarquias como «funcionário → gestor».

Veja também:·····
Anti-join (LEFT JOIN + IS NULL)
Artigo
SELECT u.*
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE o.id IS NULL;

Linhas à esquerda SEM correspondência à direita — «usuários sem pedidos». Alternativa a NOT EXISTS.

Veja também:·····

Agregação e agrupamento30

COUNT
Artigo
SELECT COUNT(*), COUNT(email) FROM users;

Conta linhas de um grupo. COUNT(*) — todas as linhas, COUNT(col) — apenas não-NULL, COUNT(DISTINCT col) — valores únicos.

Veja também:···
SELECT SUM(amount) FROM orders;

Soma de valores numéricos de um grupo. NULLs são ignorados. Retorna NULL (não 0) para grupo vazio.

SELECT AVG(price) FROM products;

Média aritmética. NULLs ficam fora do divisor. Converta uma coluna inteira para numeric ou a parte fracionária é truncada.

SELECT MIN(created_at) FROM orders;

Menor valor de um grupo. Funciona com números, datas e textos. NULLs são ignorados.

SELECT MAX(created_at) FROM orders;

Maior valor de um grupo. Funciona com números, datas e textos. NULLs são ignorados.

GROUP BY
Artigo
SELECT user_id, COUNT(*) FROM orders GROUP BY user_id;

Agrupa linhas. Toda coluna do SELECT que não seja de agregação deve estar no GROUP BY.

Veja também:···
HAVING
Artigo
SELECT user_id, COUNT(*)
FROM orders
GROUP BY user_id
HAVING COUNT(*) > 5;

Filtra sobre agregados — como WHERE, mas depois do GROUP BY.

Veja também:···
DISTINCT
Artigo
SELECT DISTINCT country FROM users;

Remove as linhas duplicadas do resultado.

Veja também:····
COUNT(*) FILTERPostgreSQL
Artigo
COUNT(*) FILTER (WHERE type = 'view') AS views

Agregado condicional: COUNT/SUM apenas sobre as linhas que satisfazem o WHERE. Substitui três consultas separadas por uma só.

Veja também:·····
STRING_AGGPostgreSQL
Artigo
STRING_AGG(name, ', ' ORDER BY created_at)

Concatena valores em uma única cadeia com um separador. O ORDER BY interno garante a ordem.

Veja também:··
ARRAY_AGGPostgreSQL
Artigo
ARRAY_AGG(amount ORDER BY created_at)

Reúne valores em um array. Útil quando uma linha de auditoria precisa de todo o histórico em uma célula.

Veja também:··
GROUPING SETSPostgreSQL
Artigo
GROUP BY GROUPING SETS ((kind), (user_id), ())

Vários níveis de agrupamento em uma consulta — linha a linha: por kind, por user_id e um total geral.

Veja também:···
ROLLUPPostgreSQL
Artigo
GROUP BY ROLLUP (DATE_TRUNC('month', ts))

O mesmo nível de agrupamento mais uma linha de total geral (uma única linha NULL no final).

Veja também:···
PERCENTILE_CONTPostgreSQL
Artigo
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY amount)

Mediana / quantil. Mais resistente a valores atípicos do que AVG.

Veja também:···
UNNESTPostgreSQL
Artigo
SELECT tag FROM articles, UNNEST(tags) tag

Expande um array em linhas — uma linha por elemento do array.

Veja também:··
COUNT(DISTINCT)
Artigo
SELECT COUNT(DISTINCT user_id) FROM events;

Conta os valores distintos. Custoso em tabelas grandes — use APPROX_COUNT_DISTINCT / HLL quando uma estimativa basta.

Veja também:···
BOOL_AND / BOOL_OR
Artigo
SELECT BOOL_AND(active), BOOL_OR(is_admin) FROM users;

Agregados booleanos: BOOL_AND é true se TODAS as linhas forem true; BOOL_OR se ao menos uma for. NULLs são ignorados.

Veja também:·
EVERY
Artigo
SELECT dept, EVERY(salary > 0) FROM emp GROUP BY dept;

O sinônimo padrão do SQL para BOOL_AND — true quando a condição vale para todas as linhas do grupo.

Veja também:·
STDDEV
Artigo
SELECT STDDEV_SAMP(amount), STDDEV_POP(amount) FROM orders;

Desvio padrão: _SAMP para uma amostra (divisor n-1), _POP para toda a população (divisor n). STDDEV sozinho equivale a STDDEV_SAMP.

Veja também:···
VARIANCE
Artigo
SELECT VAR_SAMP(amount), VAR_POP(amount) FROM orders;

Variância — o quadrado do desvio padrão. _SAMP para amostra, _POP para população. VARIANCE sozinho equivale a VAR_SAMP.

Veja também:···
MODE() WITHIN GROUPPostgreSQL
Artigo
SELECT MODE() WITHIN GROUP (ORDER BY status) FROM tickets;

A moda — o valor mais frequente do grupo. Em caso de empate vence o primeiro pelo ORDER BY.

Veja também:···
PERCENTILE_DISC
Artigo
SELECT PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY amount) FROM orders;

Percentil discreto — retorna um valor que realmente existe nos dados, diferente de PERCENTILE_CONT que interpola.

Veja também:···
BIT_AND / BIT_OR
Artigo
SELECT BIT_OR(flags), BIT_AND(flags) FROM permissions;

Agregados bit a bit sobre uma coluna integer: BIT_OR reúne todos os bits ativos, BIT_AND mantém os comuns a todas as linhas. Para máscaras de flags.

Veja também:·
JSON_AGG / JSONB_AGGPostgreSQL
Artigo
SELECT JSONB_AGG(t ORDER BY t.id) FROM tasks t;

Agrupa linhas em um array JSON — útil para retornar dados aninhados em uma única consulta. JSONB_AGG armazena como jsonb (mais rápido, sem chaves duplicadas).

Veja também:····
JSONB_OBJECT_AGGPostgreSQL
Artigo
SELECT JSONB_OBJECT_AGG(key, value) FROM settings;

Dobra pares chave-valor em um único objeto JSON. Ideal para transformar uma tabela de configurações em um mapa.

Veja também:····
CORR
Artigo
SELECT CORR(price, sales) FROM products;

Coeficiente de correlação de Pearson entre duas colunas: de -1 a 1. Uma medida de associação linear.

Veja também:···
REGR_SLOPE / REGR_INTERCEPT
Artigo
SELECT REGR_SLOPE(y, x), REGR_INTERCEPT(y, x) FROM points;

Inclinação e intercepto da reta de regressão de y sobre x — uma tendência em um único agregado, sem pacote estatístico externo.

Veja também:···
REGR_R2
Artigo
SELECT REGR_R2(y, x) FROM points;

O coeficiente de determinação R² da regressão de y sobre x: 0..1, quão bem a reta se ajusta aos dados.

Veja também:···
MAX(...) FILTER (pivot)PostgreSQL
Artigo
SELECT user_id,
  MAX(amount) FILTER (WHERE kind = 'deposit')  AS deposit,
  MAX(amount) FILTER (WHERE kind = 'withdraw') AS withdraw
FROM tx GROUP BY user_id;

Transforma linhas em colunas (pivot): MAX/SUM com FILTER por categoria. Substitui uma pilha de agregados CASE escritos à mão.

Veja também:···
CUBE
Artigo
SELECT region, product, SUM(amount)
FROM sales
GROUP BY CUBE (region, product);

Todas as combinações de agrupamento de uma vez: por region, por product, por ambos e um total geral. Para relatórios de tabela cruzada.

Veja também:···

Subconsultas3

IN (subquery)
Artigo
SELECT * FROM users WHERE id IN (SELECT user_id FROM orders);

Verifica a pertinência a uma lista gerada por outra consulta.

Veja também:···
EXISTS
Artigo
SELECT * FROM users u
WHERE EXISTS (
  SELECT 1 FROM orders o WHERE o.user_id = u.id
);

Mantém a linha se a consulta interna encontrar ao menos uma linha correspondente.

Veja também:···
Scalar subquery
Artigo
SELECT
  name,
  (SELECT COUNT(*) FROM orders o WHERE o.user_id = u.id) AS cnt
FROM users u;

Uma subconsulta que retorna um único valor — pode ficar dentro do SELECT.

Veja também:···

Operações de conjunto (UNION/INTERSECT)3

UNION / UNION ALL
Artigo
SELECT id FROM a
UNION ALL
SELECT id FROM b;

Empilha os resultados de duas consultas (mesmo número de colunas, tipos compatíveis). UNION remove duplicatas, UNION ALL as mantém (e é mais rápido).

Veja também:·
INTERSECT
Artigo
SELECT user_id FROM purchases
INTERSECT
SELECT user_id FROM refunds;

Linhas presentes em AMBAS as consultas. No MySQL — a partir da 8.0.31.

Veja também:·
EXCEPT
Artigo
SELECT user_id FROM users
EXCEPT
SELECT user_id FROM banned;

Linhas da primeira consulta que NÃO estão na segunda. No Oracle é MINUS.

Veja também:·

Funções de janela9

ROW_NUMBER
Artigo
SELECT
  name,
  ROW_NUMBER() OVER (ORDER BY score DESC) AS rn
FROM players;

Número sequencial único para cada linha dentro da janela.

Veja também:····
RANK / DENSE_RANK
Artigo
RANK() OVER (PARTITION BY dept ORDER BY salary DESC)

Classificação com saltos (RANK) ou sem saltos (DENSE_RANK) quando há empates.

Veja também:··
PARTITION BY
Artigo
SUM(amount) OVER (PARTITION BY user_id ORDER BY created_at)

Divide a janela em grupos — o agregado é calculado por grupo.

Veja também:·
LAG / LEAD
Artigo
LAG(price, 1) OVER (ORDER BY date)

Valor da linha anterior (LAG) ou seguinte (LEAD) da janela.

Veja também:··
NTILE
Artigo
NTILE(4) OVER (ORDER BY score DESC)

Divide as linhas em N grupos de tamanho igual em ordem. Com quantidades desiguais os grupos ficam 3-3-2-2 (os excedentes vão para os de número menor).

Veja também:·····
FIRST_VALUE / LAST_VALUE
Artigo
LAST_VALUE(score) OVER (
  PARTITION BY team_id ORDER BY score DESC
  ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
)

Primeiro / último valor da janela. Para LAST_VALUE é obrigatório ampliar o quadro com ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING — caso contrário, o quadro padrão corta a borda direita.

Veja também:··
PERCENT_RANK
Artigo
PERCENT_RANK() OVER (ORDER BY score DESC, player_id)

Classificação percentil de 0 a 1. Uma segunda coluna de ordenação torna o resultado determinístico quando há empates.

Veja também:··
NTH_VALUE
Artigo
NTH_VALUE(amount, 2) OVER (
  PARTITION BY customer_id ORDER BY amount DESC
  ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
)

O N-ésimo valor da janela. Também requer o quadro ampliado.

Veja também:··
Window frames
Artigo
AVG(x) OVER (ORDER BY d ROWS BETWEEN 6 PRECEDING AND CURRENT ROW)

Janelas deslizantes: «os últimos 7 dias inclusive», «média de 3 dias», etc.

Veja também:····

CTEs e recursão (WITH)5

WITH … AS
Artigo
WITH active AS (
  SELECT * FROM users WHERE status = 'active'
)
SELECT * FROM active WHERE country = 'RU';

Um resultado temporário nomeado — divide uma consulta grande em etapas.

Veja também:··
Multiple CTEs
Artigo
WITH a AS (...), b AS (...)
SELECT * FROM a JOIN b ON ...;

Vários CTEs separados por vírgulas, lidos de cima para baixo.

Veja também:··
WITH RECURSIVE
Artigo
WITH RECURSIVE chain AS (
  SELECT id, manager_id FROM emp WHERE manager_id IS NULL
  UNION ALL
  SELECT e.id, e.manager_id FROM emp e JOIN chain c ON e.manager_id = c.id
)
SELECT * FROM chain;

Percorre uma hierarquia: consulta de ancoragem → UNION ALL → passo recursivo. Ideal para organogramas, grafos e cadeias.

Veja também:··
LATERAL
Artigo
FROM customers c
LEFT JOIN LATERAL (
  SELECT * FROM orders WHERE customer_id = c.id
  ORDER BY amount DESC LIMIT 2
) l ON true

A subconsulta enxerga as colunas da linha externa. Ideal para «top-N por X». LEFT JOIN LATERAL … ON true mantém as linhas externas sem correspondência; a forma com vírgula as descarta silenciosamente.

Veja também:·····
generate_seriesPostgreSQL
Artigo
generate_series('2024-01-01'::date, '2024-01-15'::date, '1 day')

Gera um calendário / eixo. Inclui ambas as extremidades. Truque padrão para «preencher com zero os dias faltantes».

Veja também:··

Alteração de dados (DML)10

INSERT
Artigo
INSERT INTO t (col1, col2) VALUES (1, 'a'), (2, 'b');

Adiciona linhas a uma tabela.

Veja também:··
UPDATE
Artigo
UPDATE t SET col = 'x' WHERE id = 5;

Modifica linhas existentes. Sempre inclua WHERE — caso contrário, TODAS as linhas são atualizadas.

Veja também:··
DELETE
Artigo
DELETE FROM t WHERE id = 5;

Exclui linhas. Sempre inclua WHERE.

Veja também:··
ON CONFLICT DO NOTHINGPostgreSQL
Artigo
INSERT INTO t (id) VALUES (1)
ON CONFLICT (id) DO NOTHING;

Inserção idempotente — ao executar novamente, ignora silenciosamente as linhas que já existem.

Veja também:··
ON CONFLICT DO UPDATEPostgreSQL
Artigo
INSERT INTO t (id, n) VALUES (1, 1)
ON CONFLICT (id) DO UPDATE
  SET n = t.n + EXCLUDED.n;

UPSERT: inserir ou atualizar. EXCLUDED.col é o valor que tentamos inserir.

Veja também:··
MERGEPostgreSQL
Artigo
MERGE INTO t USING src ON t.id = src.id
WHEN MATCHED THEN UPDATE SET ...
WHEN NOT MATCHED THEN INSERT ...;

Postgres 15+ — alternativa ao UPSERT com ramos MATCHED / NOT MATCHED e condições em cada um.

Veja também:··
RETURNINGPostgreSQL
Artigo
INSERT INTO t (name) VALUES ('a')
RETURNING id, name;

Retorna as linhas recém-inseridas / atualizadas / excluídas na mesma instrução — sem uma segunda ida ao servidor.

Veja também:·····
DELETE … USINGPostgreSQL
Artigo
DELETE FROM orders o
USING customers c
WHERE o.customer_id = c.id AND c.country = 'US';

DELETE no estilo JOIN — filtra por outra tabela sem uma subconsulta.

Veja também:··
UPDATE … FROMPostgreSQL
Artigo
UPDATE customers c SET total = s.total
FROM (SELECT customer_id, SUM(amount) AS total FROM orders GROUP BY customer_id) s
WHERE c.id = s.customer_id;

UPDATE em massa impulsionado por uma subconsulta de agregação.

Veja também:··
CTE + DELETE … RETURNINGPostgreSQL
Artigo
WITH moved AS (
  DELETE FROM orders WHERE old RETURNING *
)
INSERT INTO archive SELECT * FROM moved;

Arquivamento atômico: move as linhas em uma única instrução, sem janela de concorrência entre DELETE e INSERT.

Veja também:··

Esquema (DDL)10

CREATE TABLE
Artigo
CREATE TABLE t (
  id INTEGER PRIMARY KEY,
  name VARCHAR(100) NOT NULL
);

Cria uma tabela com colunas tipadas.

Veja também:···
ALTER TABLE
Artigo
ALTER TABLE t ADD COLUMN created_at TIMESTAMP;

Modifica uma tabela existente.

Veja também:···
CHECK
Artigo
ALTER TABLE products
ADD CONSTRAINT price_positive CHECK (price > 0);

Rejeita valores inválidos no nível do banco de dados, não no código.

Veja também:···
FK ON DELETE
Artigo
FOREIGN KEY (post_id) REFERENCES posts(id)
  ON DELETE CASCADE   -- or SET NULL / RESTRICT

O que fazer com a linha filha quando a linha pai é excluída: propagar em cascata, definir a chave estrangeira como NULL ou bloquear.

Veja também:···
NOT VALID + VALIDATEPostgreSQL
Artigo
ALTER TABLE t
  ADD CONSTRAINT fk REFERENCES p(id) NOT VALID;
ALTER TABLE t VALIDATE CONSTRAINT fk;

Adiciona uma chave estrangeira a uma tabela grande em produção sem um bloqueio pesado: NOT VALID é instantâneo, VALIDATE não bloqueia os escritores.

Veja também:···
GENERATED column
Artigo
total NUMERIC GENERATED ALWAYS AS (price * (1 + tax)) STORED

O valor da coluna é calculado automaticamente — a fórmula fica em um único lugar.

Veja também:···
Partial UNIQUEPostgreSQL
Artigo
CREATE UNIQUE INDEX u ON users (email)
WHERE deleted_at IS NULL;

Unicidade apenas sobre as linhas ativas — para o soft-delete, de modo que os usuários possam se registrar de novo após a exclusão.

Veja também:···
Range partitioningPostgreSQL
Artigo
CREATE TABLE logs (...) PARTITION BY RANGE (ts);
CREATE TABLE logs_2024 PARTITION OF logs
  FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');

Divide uma tabela grande por intervalos. As partições antigas são removidas em milissegundos.

Veja também:···
TRIGGERPostgreSQL
Artigo
CREATE TRIGGER touch BEFORE UPDATE ON notes
FOR EACH ROW EXECUTE FUNCTION touch_updated_at();

Lógica automática no nível do banco de dados — por exemplo, atualizar updated_at sem tocar no código da aplicação.

Veja também:···
MATERIALIZED VIEWPostgreSQL
Artigo
CREATE MATERIALIZED VIEW v AS SELECT ...;
REFRESH MATERIALIZED VIEW v;

Resultado em cache de uma consulta pesada. É atualizado de forma agendada com REFRESH.

Veja também:···

Strings e datas9

LOWER / UPPER / LENGTH
Artigo
LOWER(name), UPPER(code), LENGTH(text)

Minúsculas, maiúsculas, comprimento da cadeia de caracteres.

CONCAT
Artigo
CONCAT(first_name, ' ', last_name)

Concatena cadeias de caracteres. O PostgreSQL também aceita o operador || (no MySQL, || é o OU lógico por padrão, não a concatenação).

Veja também:··
EXTRACT
Artigo
EXTRACT(YEAR FROM created_at), EXTRACT(MONTH FROM created_at)

Extrai uma parte de uma data — ano, mês, dia.

Veja também:···
DATE_TRUNCPostgreSQL
Artigo
DATE_TRUNC('month', created_at)

Trunca um timestamp para baixo até um período (dia/semana/mês). A ferramenta básica para agrupar por tempo.

Veja também:···
NOW / CURRENT_DATE + INTERVAL
Artigo
WHERE created_at >= NOW() - INTERVAL '7 days'

Instante atual (NOW()) / hoje (CURRENT_DATE) e aritmética com intervalos — «nos últimos 7 dias».

Veja também:·
CAST / ::
Artigo
CAST(price AS INTEGER)   -- or price::int

Converte um valor para outro tipo. CAST(x AS type) é padrão; x::type é a forma curta do PostgreSQL.

Veja também:·
TRIM / SUBSTRING / REPLACE
Artigo
TRIM(name), SUBSTRING(code FROM 1 FOR 3), REPLACE(phone, '-', '')

Remove espaços, extrai uma substring, substitui um fragmento. Limpeza de strings do dia a dia.

Veja também:·
SPLIT_PARTPostgreSQL
Artigo
SPLIT_PART(email, '@', 2)   -- domain from an e-mail

Divide uma string por um separador e pega a N-ésima parte. No MySQL — SUBSTRING_INDEX.

Veja também:···
ILIKEPostgreSQL
Artigo
WHERE name ILIKE '%ivan%'

LIKE sem distinção de maiúsculas (PostgreSQL). No MySQL, o LIKE comum já ignora maiúsculas com a colação padrão.

Veja também:···

Funções de string16

LEFT / RIGHT
Artigo
LEFT(code, 3), RIGHT(phone, 4)

Pega os primeiros N caracteres (LEFT) ou os últimos N (RIGHT) de uma string.

Veja também:···
POSITION / STRPOSPostgreSQL
Artigo
POSITION('@' IN email), STRPOS(email, '@')

Posição da primeira ocorrência (a partir de 1), 0 se não encontrar. STRPOS é a forma curta do PostgreSQL.

Veja também:···
LPAD / RPAD
Artigo
LPAD(id::text, 6, '0'), RPAD(name, 20, ' ')

Preenche uma string até um comprimento alvo à esquerda (LPAD) ou à direita (RPAD). Uso clássico: completar um id com zeros.

Veja também:···
INITCAPPostgreSQL
Artigo
INITCAP('john DOE')   -- John Doe

Coloca em maiúscula a primeira letra de cada palavra e o resto em minúscula. Não existe no MySQL.

Veja também:···
REPEAT
Artigo
REPEAT('ab', 3)   -- ababab

Repete uma string N vezes. Útil para placeholders e gráficos de barra em texto.

Veja também:···
REVERSE
Artigo
REVERSE(name)

Inverte uma string caractere a caractere. Às vezes usado para indexar por sufixo.

Veja também:···
char_length
Artigo
char_length(name), char_length('açai')   -- 4

Comprimento da string em CARACTERES (não bytes) — importa para UTF-8. Sinônimo de character_length.

Veja também:···
REGEXP_REPLACEPostgreSQL
Artigo
REGEXP_REPLACE(phone, '[^0-9]', '', 'g')

Substituição por expressão regular. A flag 'g' substitui todas as ocorrências; sem ela, apenas a primeira.

Veja também:·
REGEXP_MATCHESPostgreSQL
Artigo
SELECT (REGEXP_MATCHES(url, '/(\d+)'))[1] AS id;

Retorna os grupos capturados da regex como um array. Com a flag 'g' produz uma linha por correspondência.

Veja também:·
REGEXP_SPLIT_TO_ARRAYPostgreSQL
Artigo
REGEXP_SPLIT_TO_ARRAY('a, b,c', '\s*,\s*')

Divide uma string por um separador regex em um array. Há também …TO_TABLE para linhas.

Veja também:·
TRANSLATEPostgreSQL
Artigo
TRANSLATE(code, 'abc', 'xyz')   -- a->x, b->y, c->z

Substituição caractere a caractere entre dois conjuntos. Caracteres a mais do primeiro conjunto são removidos. Não é REPLACE.

Veja também:·
BTRIM / LTRIM / RTRIMPostgreSQL
Artigo
BTRIM(code, '0'), LTRIM(s), RTRIM(s, '/')

Remove os caracteres indicados de ambas as pontas (BTRIM), da esquerda (LTRIM) ou da direita (RTRIM); espaços por padrão.

Veja também:·
FORMATPostgreSQL
Artigo
FORMAT('Hi %s, id=%L', name, id)

Monta uma string a partir de um template: %s valor, %I identificador, %L literal seguro. Essencial em SQL dinâmico.

Veja também:····
STARTS_WITHPostgreSQL
Artigo
WHERE STARTS_WITH(path, '/api/')

Verifica se uma string começa com um prefixo — mais legível que LIKE 'x%'. Disponível desde o PostgreSQL 11.

Veja também:···
ascii / chrPostgreSQL
Artigo
ascii('A')   -- 65
chr(65)      -- A

Código do primeiro caractere (ascii) e o caractere de um código (chr). No MySQL a inversa se chama CHAR.

Veja também:··
to_hexPostgreSQL
Artigo
to_hex(255)   -- 'ff'

Converte um inteiro em sua string hexadecimal. Útil para cores, máscaras de bits e depuração.

Veja também:··

Números e matemática16

ROUND
Artigo
ROUND(3.14159)        -- 3
ROUND(2.5)            -- banker? no: 3

Arredonda para o inteiro mais próximo. As metades arredondam para longe do zero (2.5 → 3).

Veja também:···
ROUND(x, n)
Artigo
ROUND(3.14159, 2)     -- 3.14
ROUND(12345.6, -2)    -- 12300

Arredonda para n casas decimais; um n negativo arredonda à esquerda do ponto. Só funciona com numeric, não com float.

Veja também:···
CEIL / CEILING
Artigo
CEIL(4.1)   -- 5
CEIL(-4.1)  -- -4

Arredonda para cima até o próximo inteiro. CEILING é um sinônimo.

Veja também:···
FLOOR
Artigo
FLOOR(4.9)   -- 4
FLOOR(-4.1)  -- -5

Arredonda para baixo até o inteiro anterior. Com negativos, afasta-se do zero.

Veja também:···
TRUNCPostgreSQL
Artigo
TRUNC(3.99)     -- 3
TRUNC(3.456, 2) -- 3.45

Descarta a parte fracionária (em direção ao zero), sem arredondar. No MySQL é TRUNCATE(x, n).

Veja também:···
ABS(-7)   -- 7

Valor absoluto — a magnitude sem sinal.

Veja também:···
MOD(10, 3)   -- 1

Resto da divisão. Útil para «cada N-ésima linha» e paridade; o sinal do resultado segue o dividendo.

Veja também:···
POWER
Artigo
POWER(2, 10)   -- 1024

Eleva a uma potência. POW é um sinônimo.

Veja também:··
SQRT
Artigo
SQRT(144)   -- 12

Raiz quadrada. Um argumento negativo gera um erro.

Veja também:··
EXP / LN
Artigo
EXP(1)    -- 2.7182818...
LN(2.718) -- ~1

Exponencial e^x e logaritmo natural (base e). LN(0) e LN(negativo) geram erro.

Veja também:··
LOGPostgreSQL
Artigo
LOG(100)     -- 2  (base 10)
LOG(2, 8)    -- 3  (base 2)

No PostgreSQL LOG(x) é base 10, LOG(b, x) usa uma base arbitrária. Atenção: no MySQL LOG(x) é o logaritmo natural.

Veja também:··
SIGN
Artigo
SIGN(-42)  -- -1
SIGN(0)    -- 0

Sinal de um número: -1, 0 ou 1. Útil para ramificar conforme a direção da mudança.

Veja também:···
GREATEST / LEAST
Artigo
GREATEST(a, b, c), LEAST(a, b, c)

O maior / menor entre os argumentos dentro de uma linha (não é agregação). Argumentos NULL são ignorados.

Veja também:···
RANDOMPostgreSQL
Artigo
SELECT * FROM t ORDER BY RANDOM() LIMIT 5;

Número aleatório em [0,1). No MySQL é RAND(). ORDER BY RANDOM() dá uma amostra aleatória, mas é caro em tabelas grandes.

Veja também:
DIV (integer division)PostgreSQL
Artigo
DIV(7, 2)   -- 3
7 / 2       -- 3 when both are int

Divisão inteira que descarta o resto. No PostgreSQL / já divide inteiro quando ambos os operandos são inteiros; o MySQL usa o operador DIV para isso.

Veja também:···
WIDTH_BUCKETPostgreSQL
Artigo
WIDTH_BUCKET(score, 0, 100, 10)  -- bucket 1..10

Atribui um valor a um balde de histograma de largura igual entre dois limites. Para distribuições e agrupamento por faixas.

Veja também:····

Funções de data e hora16

AGEPostgreSQL
Artigo
AGE(end_ts, start_ts)   -- or AGE(birthday) vs now
AGE('2024-03-01', '2024-01-15')

Diferença entre duas datas como intervalo (anos/meses/dias), não em segundos. Com um único argumento conta a partir de hoje — útil para a idade.

DATE_PARTPostgreSQL
Artigo
DATE_PART('hour', created_at), DATE_PART('dow', created_at)

Forma de função do EXTRACT — extrai uma parte de data/hora como número. O campo é uma string, então é fácil passá-lo dinamicamente.

Veja também:···
EXTRACT(EPOCH FROM …)
Artigo
EXTRACT(EPOCH FROM (ended_at - started_at)) AS seconds

Converte um intervalo ou timestamp em segundos (tempo Unix). A forma padrão de medir uma duração em segundos — depois divida por 60/3600.

Veja também:···
TO_CHARPostgreSQL
Artigo
TO_CHAR(created_at, 'YYYY-MM-DD HH24:MI'), TO_CHAR(amount, 'FM999G999D00')

Formata uma data/número em uma string via um padrão (YYYY, MM, DD, HH24...). Os padrões do PostgreSQL diferem do DATE_FORMAT do MySQL.

Veja também:·
TO_DATEPostgreSQL
Artigo
TO_DATE('2024-03-15', 'YYYY-MM-DD')

Converte uma string em uma data com um padrão explícito. Mais confiável que o cast ::date quando o formato não é padrão.

Veja também:·
TO_TIMESTAMPPostgreSQL
Artigo
TO_TIMESTAMP('2024-03-15 14:30', 'YYYY-MM-DD HH24:MI')
TO_TIMESTAMP(1710512400)   -- from Unix epoch

Converte uma string em um timestamp por padrão, ou constrói um timestamptz a partir de segundos Unix (argumento numérico).

Veja também:·
CURRENT_TIMESTAMP / LOCALTIMESTAMP
Artigo
SELECT CURRENT_TIMESTAMP, LOCALTIMESTAMP;

Hora de início da transação: CURRENT_TIMESTAMP inclui fuso horário (timestamptz), LOCALTIMESTAMP não. Constante dentro de uma mesma transação.

Veja também:·
CURRENT_TIME / CURRENT_DATE
Artigo
SELECT CURRENT_DATE, CURRENT_TIME;

Apenas a data de hoje (CURRENT_DATE) ou apenas a hora (CURRENT_TIME) — sem parênteses; são valores especiais do SQL, não funções.

Veja também:·
Date arithmetic (date + int)PostgreSQL
Artigo
SELECT order_date + 7, due_date - 1, end_dt - start_dt AS days;

Você pode somar/subtrair dias inteiros de um date (date + 7). Subtrair dois date dá um número inteiro de dias; dois timestamp dão um intervalo.

Veja também:·
make_date / make_timePostgreSQL
Artigo
make_date(2024, 3, 15), make_time(14, 30, 0)

Constrói uma data ou hora a partir de números separados de ano/mês/dia, hora/minuto/segundo — sem lidar com strings de formato.

Veja também:·
make_timestamp / make_intervalPostgreSQL
Artigo
make_timestamp(2024, 3, 15, 14, 30, 0)
make_interval(days => 10, hours => 2)

Constrói um timestamp ou intervalo a partir de componentes numéricos. make_interval aceita argumentos nomeados (days =>, hours =>).

Veja também:·
AT TIME ZONEPostgreSQL
Artigo
ts_utc AT TIME ZONE 'Europe/Moscow'
local_ts AT TIME ZONE 'UTC'

Leva um instante para outro fuso horário. Sobre um timestamptz dá a hora local desse fuso; sobre um timestamp sem fuso interpreta-o como hora desse fuso.

Veja também:··
JUSTIFY_INTERVAL / JUSTIFY_HOURSPostgreSQL
Artigo
JUSTIFY_HOURS(INTERVAL '36 hours')   -- 1 day 12:00:00

Normaliza um intervalo: converte as horas excedentes em dias e os dias em meses. Transforma «50 hours» em um legível «2 days 02:00:00».

Veja também:··
DATE_BINPostgreSQL
Artigo
DATE_BIN('15 minutes', ts, TIMESTAMP '2024-01-01')

Ajusta um timestamp para o início de um bucket de largura arbitrária (ex.: 15 minutos) a partir de uma origem. Mais flexível que DATE_TRUNC. Postgres 14+.

Veja também:···
OVERLAPS
Artigo
(start_a, end_a) OVERLAPS (start_b, end_b)

Verifica se dois períodos de tempo se sobrepõem. Útil para encontrar conflitos de reservas ou turnos.

Veja também:··
Time zone cast (timestamptz)PostgreSQL
Artigo
now()::timestamptz, '2024-03-15 10:00'::timestamp

timestamptz guarda o instante em UTC e aplica o fuso na exibição; timestamp é hora «ingênua» sem fuso. Para eventos quase sempre você quer timestamptz.

Veja também:··

CASE e NULL4

CASE WHEN
Artigo
CASE
  WHEN score >= 90 THEN 'A'
  WHEN score >= 70 THEN 'B'
  ELSE 'C'
END

Lógica condicional embutida — como um if/else dentro do SELECT.

Veja também:··
COALESCE
Artigo
COALESCE(nickname, full_name, 'Anonymous')

Retorna o primeiro valor não NULL da lista.

Veja também:··
NULLIF
Artigo
NULLIF(divisor, 0)

Transforma um valor em NULL quando ele é igual ao segundo argumento. Útil para evitar a divisão por zero.

Veja também:··
NULL & IS DISTINCT FROM
Artigo
-- = NULL is never true — use IS NULL
WHERE deleted_at IS NULL
-- NULL-safe equality:
WHERE a IS DISTINCT FROM b

Comparar com NULL usando = sempre dá «desconhecido» (não TRUE/FALSE). Use IS NULL para testar; use IS DISTINCT FROM para igualdade segura com NULL.

Veja também:··

JSON / JSONB19

JSONB ->>PostgreSQL
Artigo
payload->>'target'

Extrai um valor de um JSONB como text — para operações com cadeias e comparações.

Veja também:··
JSONB @>PostgreSQL
Artigo
payload @> '{"plan":"pro"}'

O JSONB contém o fragmento indicado? Usa um índice GIN — rápido em tabelas grandes.

Veja também:···
GIN + jsonb_path_opsPostgreSQL
Artigo
CREATE INDEX idx ON events USING GIN (payload jsonb_path_ops)

Índice ideal para consultas @> sobre JSONB. Mais compacto que o jsonb_ops padrão.

Veja também:
JSONB -> / ->>PostgreSQL
Artigo
data->'user'->>'name'   -- -> keeps json, ->> as text

-> extrai um campo/elemento como jsonb (para continuar navegando), ->> como text. Chave por string, índice de array por número.

Veja também:··
#> / #>>PostgreSQL
Artigo
data #>> '{address,city}'   -- text at a nested path

Lê um valor em um caminho aninhado dado como array de chaves: #> como jsonb, #>> como text. Mais curto que encadear ->.

Veja também:··
JSONB_BUILD_OBJECTPostgreSQL
Artigo
jsonb_build_object('id', id, 'name', name)

Constrói um objeto JSON a partir de pares chave, valor alternados. Os tipos dos valores são preservados (números continuam números).

Veja também:····
JSONB_BUILD_ARRAYPostgreSQL
Artigo
jsonb_build_array(id, name, created_at)

Constrói um array JSON a partir dos argumentos dados de quaisquer tipos.

Veja também:····
JSONB_AGGPostgreSQL
Artigo
jsonb_agg(item ORDER BY created_at)

Agregado: reúne um grupo de linhas em um array JSON. O ORDER BY interno fixa a ordem dos elementos.

Veja também:····
JSONB_ARRAY_ELEMENTSPostgreSQL
Artigo
SELECT e FROM t, jsonb_array_elements(t.tags) AS e

Expande um array JSON em linhas — uma linha por elemento. A variante _text retorna text em vez de jsonb.

Veja também:·····
JSONB_ARRAY_LENGTHPostgreSQL
Artigo
jsonb_array_length(data->'items')

Comprimento de um array JSON. Gera erro se o valor não for um array — proteja com jsonb_typeof.

Veja também:·····
JSONB_SETPostgreSQL
Artigo
jsonb_set(data, '{address,city}', '"Lima"')

Retorna uma cópia do JSON com o valor do caminho substituído. create_missing=true (padrão) adiciona a chave se ela faltar.

Veja também:·
JSONB_EACHPostgreSQL
Artigo
SELECT key, value FROM jsonb_each(data)

Expande um objeto JSON em linhas (key, value) — uma por chave. A variante _text retorna value como text.

Veja também:·····
JSONB_OBJECT_KEYSPostgreSQL
Artigo
SELECT jsonb_object_keys(data)

Retorna os nomes das chaves de nível superior de um objeto JSON, uma linha por chave.

Veja também:·····
? / ?| / ?&PostgreSQL
Artigo
data ? 'email'        -- has key?
data ?| array['a','b'] -- any of these keys?

Testes de existência de chaves: ? uma chave, ?| qualquer destas, ?& todas. Apenas nível superior; suportam índice GIN.

Veja também:·····
JSONB || (merge)PostgreSQL
Artigo
data || '{"verified":true}'

Mescla dois valores JSONB: as chaves da direita sobrescrevem as da esquerda (superficial, não recursivo). Útil para uma atualização parcial.

Veja também:·
JSONB - / #- (delete)PostgreSQL
Artigo
data - 'temp'              -- drop a key
data #- '{address,zip}'    -- drop at a path

Remove uma chave/elemento: - por chave ou índice de nível superior, #- em um caminho aninhado. Retorna um novo JSONB.

Veja também:·
to_jsonbPostgreSQL
Artigo
to_jsonb(row_var)   -- whole row as a json object

Converte qualquer valor/linha/array de SQL em jsonb. Uma linha inteira da tabela vira um objeto JSON coluna → valor.

Veja também:·····
JSONB_TYPEOFPostgreSQL
Artigo
jsonb_typeof(data->'price')   -- 'number','string',...

O tipo do valor JSON como text: object, array, string, number, boolean, null. Útil antes de jsonb_array_length etc.

Veja também:·····
JSONB_PRETTYPostgreSQL
Artigo
jsonb_pretty(data)

Formata JSONB com indentação para uma saída legível ou depuração.

Veja também:·····

Desempenho e índices7

Partial indexPostgreSQL
Artigo
CREATE INDEX i ON orders (id) WHERE status = 'pending';

Índice apenas sobre o subconjunto «quente» de linhas — mais compacto e mais rápido de varrer.

Veja também:····
Composite index
Artigo
CREATE INDEX i ON orders (customer_id, created_at DESC);

Cobre o filtro e a ordenação em uma única leitura. A ordem das colunas importa.

Veja também:····
Sargable WHERE
Artigo
-- bad : WHERE EXTRACT(YEAR FROM ts) = 2024
-- good: WHERE ts >= '2024-01-01' AND ts < '2025-01-01'

Não envolva a coluna em uma função — o índice não será usado. Reescreva como um intervalo.

Veja também:····
NOT EXISTS vs NOT IN
Artigo
-- NOT IN collapses to 0 rows on any NULL
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);

NOT IN quebra silenciosamente diante de qualquer NULL na subconsulta. NOT EXISTS é seguro com NULL.

Veja também:···
CONCURRENTLYPostgreSQL
Artigo
CREATE INDEX CONCURRENTLY i ON events (user_id, kind);

Constrói um índice em uma tabela quente sem um bloqueio pesado. É proibido dentro de uma transação.

Veja também:····
EXPLAIN
Artigo
EXPLAIN SELECT * FROM orders WHERE user_id = 5;

Mostra o plano da consulta sem executá-la: quais varreduras (Seq Scan / Index Scan), ordem dos joins, linhas estimadas.

Veja também:····
EXPLAIN (ANALYZE, BUFFERS)
Artigo
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM orders WHERE user_id = 5;

Executa a consulta e mostra o tempo e as linhas REAIS versus a estimativa. Uma grande diferença estimativa↔real indica estatísticas desatualizadas ou um índice ausente.

Veja também:····

Transações4

SELECT … FOR UPDATE
Artigo
BEGIN;
SELECT * FROM accounts WHERE id IN (1, 2) FOR UPDATE;
UPDATE accounts SET balance = balance - 200 WHERE id = 1;
UPDATE accounts SET balance = balance + 200 WHERE id = 2;
COMMIT;

Bloqueia linhas até o fim da transação. Padrão para transferências de dinheiro.

Veja também:··
Conditional UPDATE
Artigo
UPDATE accounts SET balance = balance - 200
WHERE id = 1 AND balance >= 200;

Verificação e atualização em uma única instrução atômica. Se 0 linhas forem atualizadas — exiba «saldo insuficiente».

Veja também:··
FOR UPDATE SKIP LOCKED
Artigo
SELECT id FROM jobs
WHERE status = 'pending'
ORDER BY id
FOR UPDATE SKIP LOCKED LIMIT 1;

Fila de workers: cada worker pega a sua própria tarefa, ignorando as linhas bloqueadas por outros.

Veja também:··
Atomic counter
Artigo
UPDATE counters SET n = n + 1 WHERE id = 1;

Um único UPDATE incrementa o contador de forma segura diante da concorrência. SELECT seguido de UPDATE perde incrementos.

Veja também:··

Controle de acesso (GRANT/REVOKE)4

GRANT
Artigo
GRANT SELECT, INSERT ON orders TO analyst;

Concede privilégios sobre um objeto a um papel/usuário. Liste as ações necessárias (SELECT, INSERT, UPDATE, DELETE).

Veja também:··
REVOKE
Artigo
REVOKE INSERT ON orders FROM analyst;

Revoga privilégios concedidos anteriormente.

Veja também:··
CREATE ROLE
Artigo
CREATE ROLE analyst LOGIN PASSWORD 'secret';

Cria um papel (usuário/grupo). Os privilégios são concedidos ao papel, e os usuários são membros dele.

Veja também:··
Read-only role
Artigo
GRANT USAGE ON SCHEMA public TO readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO readonly;

O padrão clássico somente-leitura: acesso ao esquema + SELECT em todas as tabelas + uma regra para tabelas futuras via ALTER DEFAULT PRIVILEGES.

Veja também:··