SQL Views
Toda manhã a Ana abre o banco da Loja Aurora e digita a mesma consulta comprida: junta pedidos, clientes e itens, soma os itens, soma o frete e arredonda, para ver quanto deu cada pedido. São oito linhas de SQL, e um erro de digitação estraga tudo. Não seria bom salvar essa consulta com um nome e depois só escrever SELECT * FROM v_pedidos_total? É isso que uma view faz. Nesta aula você vai criar views com CREATE VIEW, usá-las como se fossem tabelas, apagá-las com DROP VIEW e entender o que uma view não é.
- O que é uma view: uma consulta salva com nome, que se usa como uma tabela.
- Criar views com
CREATE VIEW … AS SELECT …e consultá-las comWHERE,ORDER BY,GROUP BYeJOIN. - Por que uma view não guarda dados e por isso está sempre atualizada.
- Dar nomes às colunas da view, ver as views do banco e trocar uma view por outra com
DROP VIEW. - Para que servem as views: encurtar consultas, esconder colunas e dar nomes claros.
- View ×
WITH× tabela criada de uma consulta: qual usar. - As mensagens reais do SQLite quando uma view dá errado, incluindo o
INSERTnuma view.
Os exemplos rodam de verdade no seu navegador, num SQLite com o banco da Loja Aurora. Cada exemplo parte do banco limpo, então a view que um exemplo cria não existe no seguinte: por isso quase todo exemplo começa com o seu CREATE VIEW. As sessões de terminal saíram do sqlite3 3.50.4 no computador fictício da Ana.
A ideia: um filtro salvo na planilha
Imagine a planilha de clientes da loja, com 30 linhas. A Ana vive filtrando "só os do Piauí". Em vez de refazer o filtro toda vez, ela cria uma aba nova chamada "Clientes PI", que não tem dados próprios: ela só mostra as linhas da aba principal que passam no filtro. Quando um cliente novo do Piauí entra na aba principal, ele aparece sozinho na aba "Clientes PI".
Uma view (em português, "visão" ou "vista") é essa aba. Ela é uma consulta SELECT guardada no banco com um nome. Toda vez que alguém consulta a view, o banco roda o SELECT guardado, naquele momento, nos dados de agora. Por isso as views também são chamadas de tabelas virtuais: parecem tabelas, mas não guardam nenhuma linha.
| Tabela | View | |
|---|---|---|
| Guarda linhas? | Sim, no arquivo do banco | Não: guarda só o texto do SELECT |
Consulta com SELECT … FROM | Sim | Sim, igualzinho |
| Atualizada? | Tem o que foi gravado nela | Sempre: roda a consulta de novo a cada uso |
INSERT, UPDATE, DELETE | Sim | No SQLite, não (seção 6) |
| Cria com | CREATE TABLE | CREATE VIEW |
| Apaga com | DROP TABLE (some com os dados) | DROP VIEW (os dados ficam nas tabelas) |
1. A primeira view: CREATE VIEW
A aba "Clientes PI" da planilha, em SQL:
CREATE VIEW v_clientes_pi AS SELECT id, nome, cidade FROM clientes WHERE estado = 'PI';
- CREATE VIEW
- "Crie uma view". Guarda a consulta no banco.
- v_clientes_pi
- O nome da view. Ele não pode repetir o nome de uma tabela, índice ou outra view. O prefixo
v_é um costume (não uma regra) que avisa, a quem lê, que aquilo é uma view e não uma tabela. - AS
- "Como". Separa o nome da consulta que a view vai guardar.
- SELECT … WHERE estado = 'PI'
- Uma consulta comum, como as que você já escreve. É ela que roda toda vez que a view for usada.
O resultado foi só um "ok". Criar a view não rodou a consulta nem copiou cliente nenhum: só guardou o texto. A consulta roda quando você usa a view, no FROM, como se ela fosse uma tabela:
CREATE VIEW v_clientes_pi AS SELECT id, nome, cidade FROM clientes WHERE estado = 'PI'; SELECT * FROM v_clientes_pi;
Os 14 clientes do Piauí, só com as três colunas que a view escolheu. E dá para usar a view com tudo que você já sabe: WHERE, ORDER BY, LIMIT, COUNT…
CREATE VIEW v_clientes_pi AS SELECT id, nome, cidade FROM clientes WHERE estado = 'PI'; SELECT nome, cidade FROM v_clientes_pi WHERE cidade <> 'Teresina' ORDER BY cidade;
O banco junta as duas coisas: o WHERE estado = 'PI' da view e o WHERE cidade <> 'Teresina' da consulta. Vieram os 4 clientes do interior do Piauí.
Experimente: a vendedora da papelaria quer uma "tabela" só com os produtos dela. Na linha vazia, crie a view v_papelaria com as colunas nome e preco dos produtos da categoria 1 (categoria_id = 1). A consulta de baixo já usa a view; hoje ela dá erro, porque a view ainda não existe.
-- crie a view aqui: SELECT * FROM v_papelaria;
-- crie a view aqui: CREATE VIEW v_papelaria AS SELECT nome, preco FROM produtos WHERE categoria_id = 1; SELECT * FROM v_papelaria;
2. A view está sempre atualizada
Como a view não guarda linhas, ela nunca fica velha. Veja: a Ana cria a view, cadastra uma cliente nova de Teresina e conta os clientes da view antes e depois:
CREATE VIEW v_clientes_pi AS
SELECT id, nome, cidade
FROM clientes
WHERE estado = 'PI';
SELECT COUNT(*) AS antes FROM v_clientes_pi;
INSERT INTO clientes (nome, cidade, estado)
VALUES ('Ana Lúcia Reis', 'Teresina', 'PI');
SELECT COUNT(*) AS depois FROM v_clientes_pi;
Eram 14, viraram 15, e ninguém mexeu na view. O INSERT foi na tabela clientes; a view só olhou de novo. O mesmo vale para UPDATE e DELETE: qualquer mudança nas tabelas aparece na view na próxima consulta.
No terminal, a view fica gravada
No editor do guia, cada Rodar começa do banco limpo. No terminal, a view fica no arquivo, como as tabelas. Repare que o .tables lista a view junto com as tabelas, e que o .schema mostra o comando que a criou, com um comentário que o próprio sqlite3 acrescenta com as colunas da view:
$ sqlite3 loja.db SQLite version 3.50.4 2025-07-30 19:33:53 Enter ".help" for usage hints. sqlite> CREATE VIEW v_clientes_pi AS SELECT id, nome, cidade FROM clientes WHERE estado = 'PI'; sqlite> .tables categorias fornecedores itens_pedido produtos clientes funcionarios pedidos v_clientes_pi sqlite> .schema v_clientes_pi CREATE VIEW v_clientes_pi AS SELECT id, nome, cidade FROM clientes WHERE estado = 'PI' /* v_clientes_pi(id,nome,cidade) */; sqlite> .quit $ sqlite3 loja.db "SELECT nome, cidade FROM v_clientes_pi LIMIT 3;" « no dia seguinte, a view continua lá José Ribamar Silva|Teresina Maria Clara Mendes|Teresina Conceição Prado|Teresina
3. Uma view que poupa trabalho de verdade
A view de clientes do Piauí é curta, e talvez nem valesse a pena. O ganho aparece com consultas grandes, como a da Ana todas as manhãs: o total de cada pedido. Ela precisa de três tabelas (INNER JOIN), de GROUP BY para somar os itens de cada pedido e de ROUND para arredondar (aula Funções Numéricas). Escrita uma vez, dentro de uma view:
CREATE VIEW v_pedidos_total AS
SELECT p.id,
p.data,
c.nome AS cliente,
ROUND(SUM(i.quantidade * i.preco_unitario), 2) AS subtotal,
p.frete,
ROUND(SUM(i.quantidade * i.preco_unitario) + p.frete, 2) AS total
FROM pedidos AS p
JOIN clientes AS c ON c.id = p.cliente_id
JOIN itens_pedido AS i ON i.pedido_id = p.id
GROUP BY p.id, p.data, c.nome, p.frete;
SELECT * FROM v_pedidos_total LIMIT 4;
- c.nome AS cliente
- O apelido vira o nome da coluna da view. Quem usar a view vai escrever
cliente, e nãoc.nome. - … AS subtotal
- A soma dos itens do pedido (quantidade × preço de cada item). Sem o
AS, a coluna da view se chamariaROUND(SUM(i.quantidade * i.preco_unitario), 2): um nome horrível de usar. - … AS total
- Os itens mais o frete: o que o cliente pagou. O pedido 1 deu 30.94 de itens + 9.9 de frete = 40.84.
- GROUP BY p.id, …
- Uma linha por pedido.
Agora as perguntas do dia viram consultas curtinhas, sem nenhum JOIN à vista:
CREATE VIEW v_pedidos_total AS
SELECT p.id, p.data, c.nome AS cliente,
ROUND(SUM(i.quantidade * i.preco_unitario), 2) AS subtotal,
p.frete,
ROUND(SUM(i.quantidade * i.preco_unitario) + p.frete, 2) AS total
FROM pedidos AS p
JOIN clientes AS c ON c.id = p.cliente_id
JOIN itens_pedido AS i ON i.pedido_id = p.id
GROUP BY p.id, p.data, c.nome, p.frete;
-- os 3 maiores pedidos
SELECT id, cliente, total FROM v_pedidos_total ORDER BY total DESC LIMIT 3;
-- quem mais gastou na loja
SELECT cliente, COUNT(*) AS pedidos, ROUND(SUM(total), 2) AS gasto
FROM v_pedidos_total
GROUP BY cliente
ORDER BY gasto DESC
LIMIT 3;
A Conceição Prado é a cliente que mais gastou: 4 pedidos, 1398.03 no total. O maior pedido da loja é o 3, da Ana Beatriz Sousa: 660.0.
View dentro de view
Uma view pode usar outra. A tela "pedidos grandes" da gerente é só um filtro em cima da v_pedidos_total:
CREATE VIEW v_pedidos_total AS
SELECT p.id, p.data, c.nome AS cliente,
ROUND(SUM(i.quantidade * i.preco_unitario), 2) AS subtotal,
p.frete,
ROUND(SUM(i.quantidade * i.preco_unitario) + p.frete, 2) AS total
FROM pedidos AS p
JOIN clientes AS c ON c.id = p.cliente_id
JOIN itens_pedido AS i ON i.pedido_id = p.id
GROUP BY p.id, p.data, c.nome, p.frete;
CREATE VIEW v_pedidos_grandes AS
SELECT * FROM v_pedidos_total WHERE total >= 500;
SELECT id, data, cliente, total FROM v_pedidos_grandes;
Seis pedidos passaram de 500. Se um dia a regra do total mudar (por exemplo, descontar um cupom), basta corrigir a v_pedidos_total: a v_pedidos_grandes e todas as consultas que usam as duas passam a usar a regra nova.
4. Os nomes das colunas da view
As colunas da view herdam os nomes do SELECT: o nome da coluna original ou o apelido do AS. Também dá para escrever a lista de nomes logo depois do nome da view, entre parênteses:
CREATE VIEW v_contatos (cliente, uf, correio) AS SELECT nome, estado, email FROM clientes; SELECT * FROM v_contatos LIMIT 3;
A primeira coluna do SELECT ganha o primeiro nome da lista, a segunda ganha o segundo, e assim por diante. As duas formas dão no mesmo; escolha uma e não misture.
| Forma | Exemplo | Quando usar |
|---|---|---|
Apelidos no SELECT | CREATE VIEW v AS SELECT nome AS cliente, … | A mais comum: cada nome fica ao lado da sua expressão. |
| Lista depois do nome | CREATE VIEW v (cliente, …) AS SELECT nome, … | Quando você quer ver todos os nomes da view de uma vez, no alto. |
5. Vendo, trocando e apagando views
Quais views o banco tem
As views ficam na mesma tabela especial dos índices e das tabelas, a sqlite_schema, com type = 'view':
CREATE VIEW v_clientes_pi AS SELECT id, nome, cidade FROM clientes WHERE estado = 'PI'; SELECT type, name, sql FROM sqlite_schema WHERE type = 'view';
A coluna sql mostra que o banco guardou só o texto da consulta. No terminal, .tables e .schema fazem o mesmo serviço (seção 2).
DROP VIEW
Para apagar uma view, use DROP VIEW ("descarte a view"). Só a view some; as tabelas e os dados continuam lá, intocados:
CREATE VIEW v_clientes_pi AS SELECT id, nome, cidade FROM clientes WHERE estado = 'PI'; DROP VIEW v_clientes_pi; SELECT COUNT(*) AS clientes FROM clientes;
Trocar a consulta de uma view
O SQLite não tem um comando para alterar uma view. Para mudar a consulta, apague e crie de novo. Em scripts que rodam várias vezes, use as formas "se":
CREATE VIEW v_clientes_pi AS SELECT id, nome, cidade FROM clientes WHERE estado = 'PI'; -- a Ana quer também o email: apaga e cria de novo DROP VIEW IF EXISTS v_clientes_pi; CREATE VIEW v_clientes_pi AS SELECT id, nome, cidade, email FROM clientes WHERE estado = 'PI'; SELECT * FROM v_clientes_pi LIMIT 3;
| Comando | O que faz se a view já existe | Se não existe |
|---|---|---|
CREATE VIEW v AS … | Erro: view v already exists | Cria |
CREATE VIEW IF NOT EXISTS v AS … | Não faz nada (a view antiga continua, com a consulta antiga!) | Cria |
DROP VIEW v | Apaga | Erro: no such view: v |
DROP VIEW IF EXISTS v | Apaga | Não faz nada |
CREATE VIEW IF NOT EXISTS
Ele não troca uma view que já existe. Se você mudou a consulta e rodou de novo com IF NOT EXISTS, a view continua com a consulta velha, sem erro nenhum. Para trocar, o certo é DROP VIEW IF EXISTS seguido de CREATE VIEW.
View temporária
CREATE TEMP VIEW (de temporary, "temporária") cria uma view que só existe enquanto o banco estiver aberto. Ao fechar o sqlite3, ela some sozinha. Serve para uma análise rápida, sem deixar lixo no arquivo da loja.
6. Uma view não aceita INSERT (no SQLite)
A view parece uma tabela, e a Ana tentou cadastrar um cliente por ela:
CREATE VIEW v_clientes_pi AS
SELECT id, nome, cidade FROM clientes WHERE estado = 'PI';
INSERT INTO v_clientes_pi (nome, cidade)
VALUES ('Ana Lúcia Reis', 'Teresina');
cannot modify v_clientes_pi because it is a view: "não posso modificar v_clientes_pi porque é uma view". No SQLite, as views são só de leitura: INSERT, UPDATE e DELETE numa view dão esse mesmo erro. Faz sentido: a view não tem linhas próprias, e o banco teria de adivinhar em que tabela gravar (e que estado pôr no cliente novo). Grave sempre na tabela de verdade, clientes; a view mostra o resultado na hora.
No terminal, a mesma mensagem vem com o prefixo Parse error:, porque o SQLite recusa o comando antes de rodá-lo:
$ sqlite3 loja.db
SQLite version 3.50.4 2025-07-30 19:33:53
Enter ".help" for usage hints.
sqlite> INSERT INTO v_clientes_pi (nome) VALUES ('Ana Lúcia Reis');
Parse error: cannot modify v_clientes_pi because it is a view
O SQLite tem os triggers INSTEAD OF ("em vez de"): um comando que roda no lugar do INSERT na view e grava na tabela certa. É assunto avançado, fora deste curso; o que importa agora é saber que, sem isso, a view só serve para ler.
Missão: o script tenta cadastrar a cliente Ana Lúcia Reis, de Teresina (PI), pela view, e dá erro. Conserte o INSERT para gravar na tabela clientes, sem esquecer o estado. O SELECT do fim prova que ela aparece na view.
CREATE VIEW v_clientes_pi AS
SELECT id, nome, cidade FROM clientes WHERE estado = 'PI';
INSERT INTO v_clientes_pi (nome, cidade)
VALUES ('Ana Lúcia Reis', 'Teresina');
SELECT * FROM v_clientes_pi WHERE nome LIKE 'Ana%';
CREATE VIEW v_clientes_pi AS
SELECT id, nome, cidade FROM clientes WHERE estado = 'PI';
INSERT INTO clientes (nome, cidade, estado)
VALUES ('Ana Lúcia Reis', 'Teresina', 'PI');
SELECT * FROM v_clientes_pi WHERE nome LIKE 'Ana%';
7. Para que servem as views
| Uso | Exemplo na Loja Aurora |
|---|---|
| Encurtar consultas compridas que se repetem | v_pedidos_total: o JOIN de três tabelas vira SELECT * FROM v_pedidos_total. |
| Uma regra num lugar só | "Total = itens + frete" está escrito uma vez. Todo relatório que usa a view segue a mesma conta. |
| Esconder colunas | Uma view da equipe sem a coluna salario dos funcionários (exemplo abaixo). |
| Nomes claros | Colunas como cliente e total no lugar de c.nome e de uma fórmula. |
CREATE VIEW v_equipe AS SELECT id, nome, cargo FROM funcionarios; SELECT * FROM v_equipe;
A lista da equipe para o mural da loja, sem o salário de ninguém. Quem usar a v_equipe simplesmente não enxerga a coluna salario: pedir por ela dá no such column: salario. Num banco com servidor (MySQL, PostgreSQL, SQL Server), dá para ir além: permitir que um usuário leia a view, mas não a tabela, e aí a view vira uma proteção de verdade (aula Usuários e Permissões). No SQLite, que não tem usuários, ela é uma organização: quem abre o arquivo continua podendo ler a tabela.
Uma view roda exatamente a consulta que ela guarda, com os índices que as tabelas tiverem. Ela não é mais rápida nem mais lenta que digitar a consulta inteira. Se a v_pedidos_total ficar lenta com milhões de pedidos, a solução está nas tabelas (veja Índices), não na view.
8. View × WITH × tabela copiada
Há três jeitos de dar um nome a uma consulta. Todos eles produzem o mesmo resultado aqui, mas vivem por tempos diferentes:
-- 1. view: guardada no banco, roda a consulta a cada uso CREATE VIEW v_pi AS SELECT nome FROM clientes WHERE estado = 'PI'; SELECT COUNT(*) AS pela_view FROM v_pi; -- 2. WITH (CTE): vale só para este SELECT WITH pi AS (SELECT nome FROM clientes WHERE estado = 'PI') SELECT COUNT(*) AS pelo_with FROM pi; -- 3. tabela copiada: guarda uma FOTO das linhas de agora CREATE TABLE copia_pi AS SELECT nome FROM clientes WHERE estado = 'PI'; SELECT COUNT(*) AS pela_copia FROM copia_pi;
Os três deram 14. A diferença aparece quando os dados mudam: um cliente novo do Piauí aparece na view (seção 2) e num WITH rodado de novo, mas não na copia_pi, que é uma tabela de verdade com as 14 linhas copiadas naquele instante.
| Forma | Dura | Está sempre atualizada? | Quando usar |
|---|---|---|---|
CREATE VIEW | Até um DROP VIEW | Sim | Uma consulta que muita gente (ou muitos relatórios) usa todo dia. |
WITH nome AS (…) | Só aquele comando | Sim | Organizar uma consulta grande, de uso único (aula CTE (WITH)). |
CREATE TABLE … AS SELECT | Até um DROP TABLE | Não: é uma cópia | Guardar uma foto: o fechamento do mês, um backup antes de mexer (aula Criar Tabela a partir de Consulta). |
| Digitar a consulta toda vez | — | Sim | Consulta curta ou de uma vez só. |
Quando dá errado
CREATE VIEW v_clientes_pi AS SELECT id, nome FROM clientes WHERE estado = 'PI'; CREATE VIEW v_clientes_pi AS SELECT id, nome, email FROM clientes WHERE estado = 'PI';
O que aconteceu: view v_clientes_pi already exists, "a view já existe". O SQLite não troca a view sozinho.
Como consertar: DROP VIEW IF EXISTS v_clientes_pi; antes do segundo CREATE VIEW (seção 5).
CREATE VIEW clientes AS SELECT nome FROM clientes WHERE estado = 'PI';
O que aconteceu: table clientes already exists, "a tabela clientes já existe". Tabelas, views e índices dividem a mesma lista de nomes.
Como consertar: outro nome, de preferência com o prefixo v_.
DROP TABLE (ou o contrário)
CREATE VIEW v_clientes_pi AS SELECT id, nome FROM clientes WHERE estado = 'PI'; DROP TABLE v_clientes_pi;
O que aconteceu: use DROP VIEW to delete view v_clientes_pi, "use DROP VIEW para apagar a view". O contrário também é protegido: DROP VIEW clientes; dá use DROP TABLE to delete table clientes. Ainda bem: um DROP VIEW nunca apaga uma tabela por engano.
Como consertar: view se apaga com DROP VIEW; tabela, com DROP TABLE.
DROP VIEW v_clientes_pi;
O que aconteceu: no such view: v_clientes_pi. Aqui o banco está limpo; no terminal, acontece quando o nome foi digitado errado.
Como consertar: confira o nome (.tables no terminal) ou use DROP VIEW IF EXISTS.
CREATE VIEW v_vendas AS SELECT nome FROM vendas; SELECT * FROM v_vendas;
O que aconteceu: o CREATE VIEW deu "ok", mesmo com uma tabela vendas que não existe! O SQLite só guarda o texto; ele confere a consulta quando a view é usada. Aí veio o erro: no such table: main.vendas. O mesmo acontece se a tabela existia e depois foi apagada com DROP TABLE: a view fica órfã e quebra no próximo uso.
Como consertar: logo depois de criar uma view, rode um SELECT * FROM … LIMIT 1 nela para ter certeza de que funciona.
SELECT
CREATE VIEW v_contatos (cliente, uf, correio) AS SELECT nome, email FROM clientes; SELECT * FROM v_contatos;
O que aconteceu: de novo, o CREATE passou e o erro só veio no uso: expected 3 columns for 'v_contatos' but got 2, "esperava 3 colunas para v_contatos, mas recebeu 2". A lista tem três nomes e o SELECT, duas colunas (faltou o estado).
Como consertar: a lista de nomes e o SELECT precisam ter o mesmo número de colunas.
CREATE VIEW v_contatos AS SELECT nome, email FROM clientes; ALTER TABLE clientes DROP COLUMN email;
O que aconteceu: error in view v_contatos after drop column: no such column: email. Antes de apagar a coluna (aula ALTER TABLE), o SQLite confere se alguma view ia quebrar, e recusa. A coluna continua lá.
Como consertar: apague (ou recrie sem a coluna) a view primeiro; depois apague a coluna.
O CREATE VIEW nome AS SELECT … e o DROP VIEW são iguais no MySQL, no PostgreSQL e no SQL Server. As diferenças principais:
- Trocar uma view: PostgreSQL e MySQL têm
CREATE OR REPLACE VIEW("crie ou substitua"); o SQL Server temCREATE OR ALTER VIEW(desde o SQL Server 2016 SP1). No PostgreSQL, a consulta nova precisa manter as colunas da antiga, podendo só acrescentar outras no fim. - Gravar pela view: nos três, views simples (de uma tabela só, sem
GROUP BY,DISTINCTnem funções agregadas) aceitamINSERT,UPDATEeDELETE, que vão parar na tabela. Eles também têmWITH CHECK OPTION, que recusa gravar pela view uma linha que a view não mostraria. - View materializada: o PostgreSQL tem
CREATE MATERIALIZED VIEW, que guarda as linhas (como a tabela copiada da seção 8) e lembra a consulta; para atualizar, roda-seREFRESH MATERIALIZED VIEW.
-- PostgreSQL e MySQL CREATE OR REPLACE VIEW v_clientes_pi AS SELECT id, nome, cidade, email FROM clientes WHERE estado = 'PI'; -- SQL Server CREATE OR ALTER VIEW v_clientes_pi AS SELECT id, nome, cidade, email FROM clientes WHERE estado = 'PI';
Esses trechos não rodam no SQLite, que não tem OR REPLACE para views.
Referência rápida
| Comando | O que faz |
|---|---|
CREATE VIEW nome AS SELECT …; | Guarda a consulta com um nome |
CREATE VIEW nome (col1, col2) AS SELECT …; | Idem, dando nome às colunas |
CREATE VIEW IF NOT EXISTS nome AS …; | Cria só se não existir (não troca a que existe) |
CREATE TEMP VIEW nome AS …; | View que some quando o banco é fechado |
SELECT … FROM nome_da_view …; | Usa a view como tabela (com WHERE, JOIN, GROUP BY…) |
DROP VIEW nome; | Apaga a view (os dados ficam) |
DROP VIEW IF EXISTS nome; | Apaga só se existir |
SELECT name, sql FROM sqlite_schema WHERE type = 'view'; | Lista as views e suas consultas |
.tables / .schema nome | No terminal do sqlite3: lista / mostra a view |
| Mensagem do SQLite | Quer dizer |
|---|---|
view X already exists | Já existe uma view com esse nome |
table X already exists | O nome da view é o de uma tabela |
cannot modify X because it is a view | INSERT/UPDATE/DELETE numa view: grave na tabela |
use DROP VIEW to delete view X | Usou DROP TABLE numa view |
use DROP TABLE to delete table X | Usou DROP VIEW numa tabela |
no such view: X | O DROP VIEW não achou a view |
expected N columns for 'X' but got M | A lista de nomes da view e o SELECT não batem |
error in view X after drop column: … | Uma view usa a coluna que você quis apagar |
Exercícios
1. Complete o comando
Crie a view v_vips com os clientes VIP:
2. Apague a view
Complete para apagar a view v_vips só se ela existir:
3. A Ana criou a view v_clientes_pi e, depois, cadastrou na tabela clientes um cliente novo de Picos (PI). O que acontece na próxima consulta à view?
4. O que uma view guarda no banco?
5. No SQLite, UPDATE v_equipe SET cargo = 'Vendedora' WHERE id = 3; dá…
6. A Ana precisa guardar os totais de setembro como estavam no dia do fechamento, mesmo que alguém corrija um pedido depois. O que ela deve usar?
Missão final: a view dos atendimentos
Missão: a gerente quer ver, a qualquer hora, quantos pedidos cada vendedor atendeu. Crie a view v_atendimentos com duas colunas: vendedor (o nome do funcionário) e pedidos (quantos pedidos ele atendeu). Junte funcionarios e pedidos pelo funcionario_id e agrupe por funcionário. Só entra quem atendeu pelo menos um pedido.
-- crie a view aqui: SELECT * FROM v_atendimentos;
-- crie a view aqui: CREATE VIEW v_atendimentos AS SELECT f.nome AS vendedor, COUNT(*) AS pedidos FROM funcionarios AS f JOIN pedidos AS p ON p.funcionario_id = f.id GROUP BY f.id, f.nome; SELECT * FROM v_atendimentos;
Os seis vendedores atenderam 15 pedidos cada. A gerente Marta e o estoquista Davi não atendem pedidos, por isso ficaram de fora (com LEFT JOIN eles apareceriam com 0). Agora, quando entrar um pedido novo, a contagem da view sobe sozinha.
Resumo
- Uma view é uma consulta
SELECTguardada no banco com um nome:CREATE VIEW nome AS SELECT …;. - Ela se usa como uma tabela, no
FROM, comWHERE,ORDER BY,GROUP BY,JOINe até dentro de outra view. - A view não guarda linhas: roda a consulta a cada uso, então está sempre atualizada. Uma cópia que não muda se faz com
CREATE TABLE … AS SELECT. - As colunas da view levam os nomes do
SELECT(useAS) ou de uma lista:CREATE VIEW v (a, b) AS …. DROP VIEW nome;apaga só a view. Para trocar a consulta no SQLite:DROP VIEW IF EXISTS+CREATE VIEW.- No SQLite, a view é só de leitura:
INSERT/UPDATE/DELETEdãocannot modify … because it is a view. Grave na tabela. - O SQLite só confere a consulta da view quando ela é usada: teste a view logo depois de criar.