Visões (InterBase e Firebird)
Alexey Kovyazin, última atualização 13 de abril de 2012
Aqueles que estão familiarizados com a linguagem SQL não precisam de explicações detalhadas sobre este assunto, mas para preservar a sequência de apresentação, introduziremos uma breve definição de views.
VIEW é uma tabela virtual criada com base em uma consulta a tabelas comuns. Uma view é implementada como uma consulta, armazenada no servidor e executada toda vez que nos referimos a ela.
Vamos considerar diferentes variantes de uso de views. As views permitem criar níveis de estrutura de dados, permitindo separar a implementação do armazenamento de dados do seu tipo. Por exemplo, podemos criar uma view que seleciona dados de várias tabelas. Se os clientes usarem esta view em vez de se referirem diretamente às tabelas subjacentes, o desenvolvedor do banco de dados poderá alterar a consulta subjacente à view, modificá-la (para otimizar, por exemplo), e o cliente não notará nada - será a mesma view para ele. Além de isolarem a implementação do armazenamento de dados do usuário, as views permitem organizar os dados de forma mais conveniente e simples. O problema da “simplificação” da estrutura de dados surge quando o número de tabelas em um banco de dados se torna grande o suficiente e as inter-relações entre elas - complicadas. A view permite eliminar (ou, ao contrário, adicionar) uma parte dos dados não necessária ao cliente concreto do banco de dados (ou - necessária).
Além disso, as views permitem organizar a segurança no banco de dados InterBase de forma mais simples. Alguns usuários podem ter direitos apenas para ler/atualizar os dados na view, mas não têm direitos (e nem mesmo ideia) sobre as tabelas subjacentes à view! Para mais detalhes sobre segurança no InterBase, veja o capítulo “Segurança no InterBase: usuários, suas funções e direitos” (parte 4).
Sintaxe DDL para trabalhar com views
Agora consideraremos os comandos para criar e excluir views definidos por DDL (Data Definition Language - subconjunto do SQL, veja o glossário). Para criar uma view no InterBase, devemos usar a sentença com a seguinte sintaxe:
CREATE VIEW nome_da_view [(coluna_da_view[, coluna_da_view…])] AS [WITH CHECK OPTION]; Aqui nome_da_view é o nome da view que deve ser único dentro do banco de dados, e depois vem um grupo de nomes nem sempre obrigatórios dos campos incluídos na view: [(coluna_da_view [, coluna_da_view …])]. É essencial definir a declaração que seleciona os dados incluídos na view. Discutiremos o parâmetro opcional WITH CHECK OPTION um pouco mais adiante na parte “Views modificadas”.
Para alterar a view, teremos que recriá-la, ou seja, excluí-la e criá-la novamente. Ao excluir a view, é necessário excluir também todos os objetos dependentes - triggers, stored procedures e outras views. Esta é uma das principais inconveniências do trabalho com views: a necessidade de recriar a árvore de objetos que usam a view (existem utilitários que nos permitem fazer isso mais facilmente, por exemplo IBAlterView, veja o aplicativo “Ferramentas de administrador e designer do InterBase”). Devemos usar o seguinte comando DDL se quisermos excluir a view:
DROP VIEW nome_da_view;
Exemplos de views
Aqui está um exemplo de view simples:
CREATE VIEW MyView AS SELECT NAME, PRICE_1 FROM Table_example;
Neste exemplo, criamos uma view baseada na consulta à tabela Table_example que consideramos no capítulo “Tabelas. Chaves primárias e geradores”. Neste caso, a view consistirá em dois campos - NAME e PRICE_1, que serão selecionados da tabela Table_example sem quaisquer condições, ou seja, o número de registros na view MyView será igual ao número de registros em Table_example. No entanto, as views nem sempre são tão simples. Elas podem ser baseadas em dados de várias tabelas e até mesmo com base em outras views. Além disso, as views podem conter dados recebidos com base em diferentes expressões - inclusive com base em funções agregadas. Para considerar o uso desta aplicação de view em mais detalhes, vamos criar duas tabelas unidas por relação um-para-muitos (frequentemente tal relação é chamada de master-detail). Aqui está o script DDL para criar estas tabelas:
/\* Tabela: WISEMEN */
CREATE TABLE WISEMEN ( ID_WISEMAN INTEGER NOT NULL, WISEMAN_NAME VARCHAR(80));
/\* Definição de chaves primárias */
ALTER TABLE WISEMEN ADD CONSTRAINT PK_WISEMEN PRIMARY KEY (ID_WISEMAN);
/\* Tabela: WISEBOOK */
CREATE TABLE WISEBOOK ( ID_BOOK INTEGER NOT NULL, ID_WISEMAN INTEGER, BOOK VARCHAR(80));
/\* Definição de chaves primárias */
ALTER TABLE WISEBOOK ADD CONSTRAINT PK_WISEBOOK PRIMARY KEY (ID_BOOK);
/\* Definição de chaves estrangeiras */
ALTER TABLE WISEBOOK ADD CONSTRAINT FK_WISEBOOK FOREIGN KEY (ID_WISEMAN) REFERENCES WISEMEN (ID_WISEMAN);
Então, criamos duas tabelas - WISEMEN e WISEBOOK unidas por relação master-detail usando uma restrição de chave estrangeira - FOREIGN KEY. Vamos supor que estas tabelas armazenarão informações sobre os grandes sábios chineses e suas obras. Agora podemos criar algumas views baseadas nestas tabelas. Por exemplo, vamos criar a view mostrando quantas obras cada sábio tem:
CREATE VIEW WiseBookCount (WISEMAN, HOW_WISEBOOKS) AS SELECT M.WISEMAN_NAME, COUNT(B.BOOK) FROM WISEMEN M, WISEBOOK B WHERE (M.ID_WISEMAN = B.ID_WISEMAN) GROUP BY M.WISEMAN_NAME
Preste atenção que ao usar quaisquer expressões calculadas como funções agregadas COUNT (), SUM (), MAX (), etc., é essencial usar nomes definidos dos campos da view, ou seja, dar nomes a todos os campos retornados pela consulta. Como podemos ver neste exemplo, esses nomes não precisam necessariamente coincidir com os nomes dos campos da consulta, mas sua quantidade deve coincidir com a quantidade de campos retornados pela consulta. A definição de qual campo retornado pela consulta corresponde a qual campo da view é feita por número de série - o primeiro campo da consulta será refletido no primeiro campo da view, o segundo - no segundo, etc.
E se quiséssemos saber qual dos sábios escreveu mais livros? Tentaremos adicionar a expressão de ordenação - ORDER BY à consulta subjacente à view. No entanto, esta tentativa será malsucedida: o uso de ordenação ORDER BY em views não é permitido e ao tentar criar a view com a consulta contendo ORDER BY, ocorrerá um erro. Se quisermos ordenar os resultados retornados pela view, teremos que fazer isso em nome do cliente:
SELECT * FROM WiseBookCount ORDER BY HOW_WISEBOOKS
A execução desta consulta SQL levará a um resultado desejável. Além da restrição para usar a expressão ORDER BY em views, também não podemos usar o conjunto de dados recebido como resultado da execução de stored procedures como fonte de dados (veja o capítulo “Stored procedures” abaixo).
Talvez valha a pena dar mais um exemplo ilustrando a aplicação de views. Vamos supor que temos que exibir uma lista de sábios cujo nome começa com a letra “K”. Neste caso, usaremos a view com condições:
CREATE VIEW WiseMen2 (WISEMAN) AS SELECT M.WISEMAN_NAME FROM WISEMEN M WHERE M.WISEMAN_NAME LIKE ‘K%’
Assim, é fácil criar views que desempenham o papel de fornecedores de dados constantemente atualizáveis, selecionando-os de um banco de dados de acordo com condições definidas.
Views modificadas
Mencionamos acima que existe a capacidade de criar views de dados modificadas. É realmente assim - existe a capacidade não apenas de ler os dados da view, mas também de modificá-los!
Existem duas maneiras de tornar a view modificada. A primeira maneira é aplicada quando a view é criada com base em uma tabela única (ou outra view modificada), e todas as colunas da tabela dada devem permitir a presença de NULL. Assim, a consulta na qual a view se baseia não pode conter subconsultas, funções agregadas, UDF, stored procedures, declarações DISTINCT e HAVING. Se todas estas condições forem cumpridas, a view se torna automaticamente modificada, ou seja, podemos executar as consultas DELETE, INSERT e UPDATE para ela, que alterarão os dados na tabela-fonte.
A lista de condições é bastante impressionante e restringe muito a aplicação de tais views modificadas, consequentemente elas são usadas raramente.
Para tornar uma view modificada que viole qualquer uma das condições acima listadas, o mecanismo de triggers é aplicado. Para mais detalhes sobre triggers, veja o capítulo “Triggers” (parte 1). Agora consideraremos apenas os princípios gerais de organização da alteração de dados em VIEW.
Para implementação de uma view atualizada usando triggers, o seguinte deve ser feito. Criar 3 triggers para a view dada para os eventos: BEFORE DELETE, BEFORE UPDATE e BEFORE INSERT. Descrever nestes triggers o que deve ser feito com os dados ao excluir, atualizar e inserir.
Então devemos usar a view dada em consultas de modificação - DELETE, INSERT ou UPDATE. Quando o InterBase receber esta consulta, ele verificará se existem triggers apropriados para a view dada, ou seja, BEFORE DELETE/INSERT/UPDATE. Se o trigger para a ação executável existir, o InterBase o chamará para modificação dos dados reais nas tabelas subjacentes à view (embora possam ser outros dados - não há restrições de texto destes triggers), e então relerá a string (ou strings) sobre a qual a modificação foi realizada.
Assim, existe a capacidade de realizar cadeias complexas de atualização de dados em views.
A opção WITH CHECK OPTION foi mencionada na descrição da sintaxe de criação da view. Se esta opção for definida ao criar uma view modificada, cada string de dados inserida ou alterada nesta view será verificada quanto à condição de entrar na view. Pode ser explicado assim: se um novo registro inserido pelo usuário ou recebido como resultado da atualização do registro existente não satisfizer as condições da consulta, que é o fornecedor de dados para a VIEW, a inserção deste registro será cancelada e ocorrerá um erro.
Conclusão
Apesar da aparente simplicidade de criar e usar views, elas fornecem grandes capacidades para melhorar a organização de dados em um banco de dados e permitem criar uma hierarquia de organização de dados.
Alguns designers de aplicativos de banco de dados usam views com muita frequência em seu trabalho, outros evitam sua aplicação, motivando isso pela complexidade de modificação das views e pela tendência de preservar o esquema do banco de dados o mais simples e eficiente possível. Cabe a você como aplicará views em seu trabalho. O ponto mais importante é lembrar da existência de uma ferramenta tão poderosa como a view, e saber como usá-la.