Exibições SQL explicadas: crie, use e evite as armadilhas, com exemplos

  1. Início
  2. Blog
  3. Bancos de dados e SQL

Bancos de dados e SQL

Exibições SQL explicadas: Crie, use e evite as armadilhas, com exemplos

Uma visualização é uma consulta salva que você pode usar como uma tabela. Aprenda como criar uma, por que as visualizações mantêm os relatórios consistentes, o que elas fazem e o que não fazem para melhorar o desempenho e as armadilhas que as quebram.

8 min de leitura
Exibições SQL explicadas: crie, use e evite as armadilhas, com exemplos

Principais pontos

  • Uma visualização é uma consulta nomeada e armazenada que você pode selecionar como uma tabela.
  • Uma visualização normal não armazena dados, por isso sempre mostra os resultados atuais.
  • As visualizações simplificam consultas complexas, mantêm a lógica de negócios consistente e podem restringir o acesso às colunas.
  • Eles não tornam uma consulta mais rápida por si só, embora visualizações materializadas possam.

A mesma consulta de relatório de vinte linhas foi copiada em cinco painéis e cada cópia mudou um pouco. Um conta os pedidos cancelados, enquanto outro não. Visualizações SQL resolvem isso definindo essa lógica uma vez, no banco de dados, com um nome claro.

Executamos todos os exemplos abaixo no SQLite 3.50 e os resultados mostrados vêm dessa execução. As visualizações são SQL padrão, mas detalhes como atualização por meio de uma visualização, visualizações materializadas e tratamento de dependências variam entre os bancos de dados, e nós apontamos isso.

O que é uma visão?

Uma visualização é uma instrução SELECT salva no banco de dados com um nome. Quando você consulta a visualização, o banco de dados executa a consulta salva. Ela atua como uma tabela para leitura, mas uma visualização normal não contém sua própria cópia dos dados.

Pense em um filtro salvo em uma planilha. O filtro não é uma segunda cópia da planilha. É uma forma de olhar para os mesmos dados, que refletem sempre os valores mais recentes.

As tabelas de amostra

CREATE TABLE customers (
  id INT PRIMARY KEY, name TEXT, city TEXT, email TEXT, credit_limit INT
);
CREATE TABLE orders (
  id INT PRIMARY KEY, customer_id INT, total INT, status TEXT
);

INSERT INTO customers VALUES
 (1,'Asha','Pune','asha@example.com',50000),
 (2,'Ben','Delhi','ben@example.com',20000),
 (3,'Chitra','Pune','chitra@example.com',80000);

INSERT INTO orders VALUES
 (101,1,1200,'paid'), (102,1,800,'paid'),
 (103,2,300,'pending'), (104,3,2500,'paid');

Crie uma visualização

Esta visualização resume os pedidos de cada cliente. Ele esconde uma junção, agrupamento e uma expressão CASE atrás de um nome simples:

CREATE VIEW customer_sales AS
SELECT c.id, c.name, c.city,
       COUNT(o.id) AS orders,
       COALESCE(SUM(CASE WHEN o.status = 'paid' THEN o.total END), 0) AS paid_total
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.id, c.name, c.city;

Agora qualquer um pode usá-lo, sem saber como funciona:

SELECT * FROM customer_sales ORDER BY paid_total DESC;

-- 3 | Chitra | Pune  | 1 | 2500
-- 1 | Asha   | Pune  | 2 | 2000
-- 2 | Ben    | Delhi | 1 |    0

SELECT name, paid_total FROM customer_sales WHERE city = 'Pune';

-- Asha   | 2000
-- Chitra | 2500

Ben aparece com zero, porque a visualização usa LEFT JOIN e COALESCE. Decisões como essa, tomadas uma vez na visualização, são exatamente o que mantém a consistência dos relatórios. Para atualizar sua compreensão do tratamento de NULL, consulte Valores SQL NULL.

As visualizações são sempre atuais

Como uma visualização normal sempre executa sua consulta, novos dados aparecem imediatamente. Adicionamos um pedido pago para Ben e consultamos a visualização novamente:

INSERT INTO orders VALUES (105, 2, 900, 'paid');

SELECT name, paid_total FROM customer_sales WHERE name = 'Ben';

-- Ben | 900

Não houve etapa de atualização nem cópia para manter sincronizada. Esta é a principal diferença entre salvar os resultados da consulta em uma tabela separada.

Ocultando colunas

As visualizações costumam ser usadas para expor apenas as colunas que uma pessoa ou aplicativo precisa. Aqui, os endereços de e-mail e os limites de crédito são deixados de fora:

CREATE VIEW public_customers AS
SELECT id, name, city FROM customers;

-- columns: id, name, city

Em bancos de dados com permissões, como PostgreSQL, SQL Server e MySQL, você pode conceder ao usuário de relatório acesso à visualização, mas não à tabela subjacente. SQLite não possui contas de usuário, então só poderíamos mostrar a própria restrição da coluna. Trate uma visualização como uma camada de proteção. Os dados confidenciais ainda precisam de controle de acesso adequado, e alguns bancos de dados oferecem segurança em nível de linha para filtrar linhas por usuário.

Desempenho: as visualizações não aumentam a velocidade

Um mito comum é que as visualizações tornam as consultas mais rápidas. Uma visualização normal é substituída por sua definição quando você a consulta, de modo que o banco de dados faz o mesmo trabalho como se você mesmo tivesse escrito a consulta completa. Nosso plano de execução mostrou a junção e o agrupamento da visualização sendo executados como parte da consulta:

EXPLAIN QUERY PLAN SELECT * FROM customer_sales WHERE city = 'Pune';

-- CO-ROUTINE customer_sales
-- SCAN c ...
-- SEARCH o USING AUTOMATIC COVERING INDEX (customer_id=?) LEFT-JOIN
-- USE TEMP B-TREE FOR GROUP BY
-- SCAN customer_sales

Portanto, uma visualização de uma consulta lenta ainda é uma consulta lenta. A velocidade vem dos índices e de um bom design de consulta, conforme abordado em Otimização de consulta SQL e Explicação sobre índices SQL. Cuidado também com as visualizações baseadas em outras visualizações. Camadas de aninhamento facilitam a união da mesma mesa grande várias vezes sem perceber.

Visualizações materializadas

Uma visão materializada armazena seus resultados, como uma tabela em cache. As leituras são rápidas, mas os dados são tão recentes quanto a última atualização.

-- PostgreSQL
CREATE MATERIALIZED VIEW daily_sales AS
SELECT order_date, SUM(total) AS revenue FROM orders GROUP BY order_date;

REFRESH MATERIALIZED VIEW daily_sales;
Recurso Visualização normal Visualização materializada
Armazena dados Não Sim
Frescura Sempre atual Desde a última atualização
Velocidade de leitura Igual à consulta Rápido
Custo de armazenamento Nenhum Sim
Bom para Simplificando, consistência Relatórios e painéis pesados

O suporte varia. PostgreSQL e Oracle possuem visualizações materializadas e o SQL Server oferece visualizações indexadas com suas próprias regras. SQLite e MySQL não os possuem, então as pessoas usam uma tabela de resumo regular atualizada de acordo com uma programação. Não executamos o exemplo do PostgreSQL para este artigo.

Dica: Antes de criar uma visualização materializada, decida até que ponto os dados podem ficar obsoletos. “Atualizado a cada hora” deve ser aceitável para as pessoas que leem o relatório, então diga-lhes.

Você pode atualizar uma visualização?

Depende do banco de dados e da visualização. Uma visualização simples de uma única tabela, sem agrupamento ou DISTINCT, muitas vezes pode ser atualizada no PostgreSQL, MySQL e SQL Server, e a alteração passa para a tabela. Uma visualização com junções ou agregações geralmente não pode, porque o banco de dados não consegue dizer qual linha alterar.

O SQLite não permite gravações diretas nas visualizações. Nossa tentativa falhou:

INSERT INTO customer_sales (name) VALUES ('X');

-- cannot modify customer_sales because it is a view

Alguns bancos de dados suportam gatilhos INSTEAD OF para tornar uma visualização gravável, e muitos oferecem WITH CHECK OPTION, que interrompe gravações que não seriam visíveis na visualização. Na prática, a maioria das equipes mantém as visualizações somente leitura e grava nas tabelas.

Dependências e quebras

Uma visualização depende das tabelas das quais ela lê. Criamos uma visualização em uma tabela e depois eliminamos a tabela:

CREATE TABLE ghost AS SELECT 1 AS x;
CREATE VIEW v_ghost AS SELECT x FROM ghost;
DROP TABLE ghost;

SELECT * FROM v_ghost;
-- no such table: main.ghost

SQLite permitiu a queda e só falhou mais tarde, quando a view foi usada. Outros bancos de dados, como PostgreSQL, recusam-se a eliminar uma tabela da qual uma visualização depende, a menos que você adicione CASCADE, o que também remove a visualização. De qualquer forma, renomear ou eliminar uma coluna pode interromper as visualizações, portanto, verifique-as em seu teste de regressão após alterações no esquema.

Há também uma armadilha sutil com SELECT * em uma visualização. Criamos CREATE VIEW star AS SELECT * FROM customers e depois adicionamos uma coluna à tabela. No SQLite, a visualização pegou a nova coluna. Outros bancos de dados, incluindo o PostgreSQL, expandem a lista de colunas quando a visualização é criada, para que novas colunas não apareçam. Portanto, liste as colunas explicitamente. Ele documenta a visualização e se comporta da mesma forma em todos os lugares.

Gerenciando visualizações

Tarefa Sintaxe comum
Criar CRIAR VISUALIZAÇÃO nome AS SELECT ...
Substituir CREATE OR REPLACE VIEW (PostgreSQL, MySQL, Oracle)
Substituir no SQL Server CRIAR OU ALTERAR VISUALIZAÇÃO
Remover Nome DROP VIEW
Remova com segurança DROP VIEW SE EXISTE nome

A eliminação de uma visualização remove apenas a consulta salva. Em nosso teste, a tabela customers ainda tinha todas as três linhas após eliminar public_customers. Mantenha as definições de visualização no controle de versão junto com suas migrações, para que as alterações sejam revisadas como qualquer outro código.

Ver vs CTE vs tabela

Opção Vitalício Armazena dados Melhor para
Ver Até cair Não Lógica compartilhada usada por muitas consultas
CTE Uma declaração Não Organizando uma única consulta complexa
Visualização materializada Até cair Sim Leituras rápidas de resultados dispendiosos
Mesa Até cair Sim Os dados reais

Erros comuns

  • Esperando um aumento de velocidade. Uma visualização normal executa sua consulta todas as vezes.
  • Usando SELECT * em visualizações. O comportamento difere entre bancos de dados quando as tabelas são alteradas.
  • Aninhamento profundo. Visualizações criadas em visualizações ocultam junções caras.
  • Usando ORDER BY dentro de uma visualização. A ordem não é garantida quando você a consulta, então classifique na consulta externa.
  • Nomes pouco claros. Um prefixo como v_ ou um substantivo claro como customer_sales ajuda.
  • Esquecimento de visualizações durante migrações. Teste-as após cada alteração de esquema.

Considerações finais

As visualizações são uma maneira simples de fornecer uma lógica importante no banco de dados. Use-os para manter os relatórios consistentes e ocultar colunas desnecessárias, não como um truque de desempenho. Para começar, encontre uma consulta que apareça em vários lugares do seu código, transforme-a em uma visualização com colunas explícitas e aponte cada chamador para ela.

Perguntas frequentes

O que é uma visualização em SQL?

Uma visualização é uma consulta SELECT salva com um nome. Você o consulta como uma tabela, e o banco de dados executa a consulta subjacente todas as vezes, para que os resultados sejam sempre atuais.

Uma visualização SQL armazena dados?

Uma visualização normal não armazena dados, apenas a consulta. Uma visão materializada armazena resultados e deve ser atualizada para se manter atualizada.

As visualizações são mais rápidas que as tabelas?

Não. Uma visualização normal faz o mesmo trabalho que sua consulta subjacente. As visualizações materializadas podem acelerar as leituras, às custas do armazenamento e da atualização.

Você pode inserir em uma visualização?

Às vezes. Visualizações simples de tabela única geralmente podem ser atualizadas no PostgreSQL, MySQL e SQL Server. Visualizações com junções ou agrupamentos geralmente não são, e o SQLite não permite isso.

O que acontece com uma visualização se a tabela for eliminada?

Depende do banco de dados. Alguns se recusam a descartar a tabela enquanto uma visualização depende dela, enquanto outros permitem isso e a visualização falha quando consultada.

Continue aprendendo

Trabalhe com Stack Quora

Precisa de ajuda com testes, WordPress ou SEO?

Ajudamos as equipes a fornecer software melhor e a expandir seus sites. Conte-nos no que você está trabalhando e sugeriremos um próximo passo claro.

Continue lendo

Mais guias sobre testes, IA e desenvolvimento moderno

Gostou deste artigo? Escolha um tópico e vá direto para nossos tutoriais mais recentes.

Inteligência artificial

Explicação das alucinações de IA: por que os modelos de linguagem inventam as coisas e como reduzi-las

Explicação das alucinações de IA: o que são, por que os modelos de linguagem as produzem, tipos comuns, como reduzi-las com aterramento e instruções…

Leia o artigo →
DevOps

Variáveis de ambiente explicadas: arquivos .env, segredos e configuração bem feitos

Variáveis de ambiente explicadas com exemplos de Python que executamos: leitura e configuração, por que cada valor é uma string, arquivos .env, hera…

Leia o artigo →
Desenvolvimento de software

Explicação da limitação de taxa de API: algoritmos, cabeçalhos e tratamento de erros 429

Limitação de taxa de API explicada com uma simulação que executamos: token bucket, janela fixa, janela deslizante, 429 respostas, cabeçalhos de limi…

Leia o artigo →
Automação de testes

Zombando em Python: unittest.mock, patch e os erros que fazem os testes mentirem

Zombaria em Python com unittest.mock, testado: Mock e return_value, side_effect, patch onde um nome é usado, especificação e autospec, zombaria de d…

Leia o artigo →
Teste de software

Cobertura de código explicada: cobertura de linha versus filial e o que 100% realmente significa

Cobertura de código explicada com uma execução cobertura.py real: cobertura de linha, ramal e condição, leitura de um relatório, por que 100% de cob…

Leia o artigo →
Bancos de dados e SQL

DELETE vs TRUNCATE vs DROP em SQL: diferenças, reversão e quando usar cada um

DELETE vs TRUNCATE vs DROP explicado com SQL testado: o que cada um remove, rollback, aciona, redefinição de identidade, velocidade e como PostgreSQ…

Leia o artigo →
Bancos de dados e SQL

Exibições SQL explicadas: crie, use e evite as armadilhas, com exemplos

Visualizações SQL explicadas com consultas que executamos: criação de uma visualização, resultados ao vivo, ocultação de colunas, desempenho, visual…

Leia o artigo →
Desenvolvimento de software

Interface TypeScript vs tipo: diferenças reais, testadas com o compilador

Interface TypeScript versus tipo, verificada com o compilador real: o que ambos podem fazer, o que apenas um pode fazer, mesclagem de declarações, e…

Leia o artigo →
Desenvolvimento de software

Python *args e **kwargs explicados: funções flexíveis com exemplos claros

Python *args e **kwargs explicados com o código que executamos: empacotamento e descompactação, ordem dos parâmetros, argumentos somente de palavras…

Leia o artigo →
Desenvolvimento de software

Funções Python Lambda: sintaxe, usos reais e quando não usá-los

Funções lambda do Python explicadas com o código que executamos: sintaxe, classificação com chave, mapa e filtro, fechamentos, armadilha de ligação …

Leia o artigo →
Inteligência artificial

O que são agentes de IA? Como eles funcionam, com um loop de agente simples que você pode executar

O que são agentes de IA? Um guia simples para o loop do agente, ferramentas, memória e proteções, com um pequeno loop Python que executamos, riscos …

Leia o artigo →
DevOps

Monitoramento versus observabilidade: a verdadeira diferença, com logs, métricas e rastreamentos

Explicação do monitoramento versus observabilidade: falhas conhecidas e desconhecidas, logs, métricas e rastreamentos, um passo a passo do incidente…

Leia o artigo →
DevOps

Docker Volumes vs Bind Mounts: persista os dados do contêiner da maneira certa

Volumes Docker versus montagens de ligação explicadas: por que os dados do contêiner desaparecem, volumes nomeados, montagens de ligação, tmpfs, exe…

Leia o artigo →
Automação de testes

TDD vs BDD: principais diferenças, um recurso criado de ambas as maneiras e quando usar cada um

TDD vs BDD explicado com um recurso de desconto construído em ambos os sentidos: refatoração vermelho-verde com o código que executamos, cenários da…

Leia o artigo →
Desenvolvimento de software

Git merge vs rebase: diferenças, exemplos e quando usar cada um

Git merge vs rebase explicado com saída real do log, uma tabela comparativa, a regra de ouro do rebase e um fluxo de trabalho seguro para equipes.

Leia o artigo →
Desenvolvimento de software

List comprehension em Python: sintaxe, exemplos e quando evitar

List comprehension em Python explicada: sintaxe, filtros, if-else, laços aninhados, tempos medidos e quando um laço for comum é a melhor escolha.

Leia o artigo →
Bancos de dados e SQL

SQL JOIN explicado com exemplos (Inner, Left, Right, Full)

Entenda os joins SQL passo a passo com tabelas e consultas de exemplo: INNER, LEFT, RIGHT, FULL, CROSS e SELF, além de erros comuns e dicas de desem…

Leia o artigo →