Seu guia prático para execução de consultas

Neste artigo você terá a oportunidade de aprender a usar a linguagem SQL para execução de consultas e subconsultas. Serão apresentados os conceitos necessários para a realização de consultas através de um encadeamento especialmente preparado para tornar interessante o seu aprendizado.

Os Sistemas Gerenciadores de Bancos de Dados Relacionais (SGBDr) são o principal mecanismo de suporte ao armazenamento de dados e recuperação de informações utilizadas em diversas aplicações. Em um SGBD, os dados do banco de dados são mantidos em tabelas, o que torna imprescindível o conhecimento dessa estrutura.

Anatomia de uma tabela

A tabela é uma estrutura matricial composta por linhas e colunas. Na prática, cada linha representa um objeto do negócio e cada coluna representa uma característica dele. Por exemplo, a Tabela 1 (CLIENTE) representa um cadastro de clientes. Cada cliente possui código, nome, sexo, CPF, data de nascimento e salário.

#CODIGO NOME SEXO CPF NASCIMENTO SALARIO
1 Alcides Masculino 111222333-44 1/12/1975 R$ 7.000,00
2 Cristiano Masculino 222333444-55 12/3/1970 R$ 7.000,00
3 Cristiane Feminino 333444555-66 20/7/1977 R$ 1.500,00
4 Marcos Masculino 1111234333-44 19/8/1989 R$ 3.500,00
5 Joice Feminino 222444555-66 20/7/2001 R$ 2.500,00
Tabela 1. Cliente

As linhas de uma tabela são conhecidas por registros ou tuplas. Já as colunas, por campos ou atributos. No desenho, a primeira linha representa os nomes das colunas.

Dica SQL. Em expressões SQL, é possível referenciar o conteúdo de qualquer coluna através da convenção NomeTabela.NomeColuna. Por exemplo, para referenciar o campo CPF da tabela CLIENTE, pode-se usar CLIENTE.CPF. A maioria dos SGBDs permite que o usuário omita o nome da tabela, exigindo apenas a sintaxe completa no caso da existência de colunas com mesmo nome.

Na prática, a construção de um banco de dados envolve a criação de diversas tabelas relacionadas. O relacionamento entre tabelas ocorre através do uso de um mecanismo denominado chave estrangeira. Para maiores detalhes sobre relacionamentos entre tabelas.

Entendendo relacionamentos entre tabelas

Relacionamentos entre tabelas ajudam a manter íntegros os dados do banco de dados. Para aprender sobre o mecanismo de relacionamento, é interessante estudar as definições de chave primária e de chave estrangeira:

  • A chave primária serve para identificar de forma única cada linha de uma tabela. Para isso, é utilizada uma coluna ou uma combinação de colunas da própria tabela. Quando uma chave primária é escolhida, o próprio SGBD se encarrega de realizar as verificações necessárias para manter a integridade dos dados (a chave primária não pode conter valor nulo). Por exemplo, no modelo composto pelas Tabelas 1 e 2, a chave primária da tabela CLIENTE é o campo Código e a da tabela FONE é representada pelos campos Código, Fone e Tipo.
  • A chave estrangeira serve para realizar ligações entre tabelas. Tais ligações, ou relacionamentos, são essenciais para ajudar a manter íntegros os dados do banco de dados. Por exemplo, na tabela FONE o campo Código representa a chave estrangeira. Na prática, a tabela FONE depende da tabela CLIENTE. Sendo assim, para que determinado telefone seja cadastrado, é necessário que exista um cliente correspondente na tabela CLIENTE. Neste caso, um cliente pode não ter telefone (cliente Pedro) ou pode possuir vários (cliente Alcides, por exemplo).
#CODIGO #FONE #TIPO
1 34569789 residencial
1 99009988 celular
3 88223456 celular
4 23459899 residencial
2 87789009 celular
Tabela 2. Fone

A vantagem da linguagem SQL reside no fato dela ser declarativa, ou seja, todo o esforço de codificação de nossa parte é resumido na escrita de solicitações que são submetidas ao SGBD, não importando (pelo menos se não pensarmos em otimização de consultas) a forma que o mesmo utilizará para recuperar as informações.

Uma sintaxe para consultas

Estudada a composição de uma tabela e ciente da importância das chaves primária e estrangeira na manutenção da integridade dos dados do banco de dados, é chegada a hora de conhecer os principais comandos utilizados para a realização de consultas. Para isso, observe o código presente na Figura 1, camisa bastante utilizada por diversos leitores desta revista.

Sintaxe SQL para a execução de consultas
Figura 1. Sintaxe SQL para a execução de consultas

A Figura 1 representa a sintaxe SQL utilizada pela maioria dos SGBD. Observe o significado de cada comando:


SELECT [DISTINCT | ALL] {*|table.*|[table].field1}

Esta linha serve para apresentar ao usuário as colunas (field) especificadas;

As colunas podem existir em alguma tabela, ou podem ser calculadas através do uso de alguma função especial (AVG, SUM, COUNT, etc);

As linhas resultantes de uma consulta podem apresentar mesmo conteúdo. Utiliza-se DISTINCT para remover linhas repetidas. Para que sejam apresentadas linhas iguais, utiliza-se opção ALL. Na prática, esta opção é utilizada como padrão na maioria dos SGBDs;

table.* indica a recuperação de todas (*) as colunas de determinada tabela da consulta. Para recuperar apenas determinado atributo, substitui-se o * pelo nome da coluna [table].field1.


- FROM table [, ...]

Nesta linha são declaradas as tabelas envolvidas na consulta;

Em consultas envolvendo várias tabelas, é necessário indicar os campos que fazem parte do relacionamento para que o SGBD possa recuperar corretamente as informações.

É interessante notar que o nome de qualquer tabela pode ser virtualmente modificado, principalmente para facilitar a escrita das consultas.


[WHERE criteria]

Aqui são declarados os mecanismos (conjunto de condições e filtros) necessários à obtenção da informação;

É possível compor diversos critérios de filtro, usando-se para esse fim uma combinação de operadores lógicos (AND, OR, NOT), subconsultas, operadores de pesquisa em cadeia de caracteres, funções de data, entre outros;

Em consultas envolvendo várias tabelas, pode-se estabelecer a condição de ligação entre elas.


[GROUP BY groupfieldlist]

Esta opção é utilizada para agrupar informações em uma consulta;

Em groupfieldlist declara-se um conjunto de atributos os quais o SGBD considerará um grupo;

Quando utilizado em conjunto com funções de agregação (por exemplo, AVG e SUM), os resultados dessas funções são calculados para cada grupo declarado em groupfieldlist.


[HAVING groupcriteria]

De maneira semelhante à WHERE, esta opção serve para realizar filtros na consulta;

Os filtros realizados por HAVING são executados após a operação de grupamento ter sido executada. Neste caso, é possível utilizar funções de agregação como critérios de filtro.


[ORDER BY field1 [ASC | DESC]

É utilizada para ordenar o resultado da consulta;

É possível escolher, para cada coluna, o tipo de ordenação (ascendente ou descendente);

A maioria dos SGBD utiliza como padrão a ordenação ascendente, neste caso tornando desnecessária a declaração do critério ASC.

Nesta parte, realizamos uma breve revisão sobre conceitos do mundo relacional de dados, além da apresentação de uma sintaxe SQL para recuperação de informação.

Praticando consultas

Para os exemplos, serão utilizadas as tabelas CLIENTE e FONE, apresentadas na primeira parte do tutorial.


SELECT *

FROM CLIENTE
Exemplo 01. Listar todas as informações da tabela CLIENTE

Comentário: neste caso, o * substitui a declaração de todos os campos da tabela CLIENTE. Outra forma de realizar esta consulta é:


SELECT CLIENTE.*

FROM CLIENTE

É possível também escrever a consulta da seguinte forma, renomeando (virtualmente) a tabela CLIENTE:


SELECT C.*

FROM CLIENTE C
Exemplo 02. Listar o nome e a data de nascimento de todos os clientes

SELECT nome, nascimento

FROM CLIENTE

Aqui, bastou inserir na cláusula SELECT os campos correspondentes à informação pedida. Outra forma de realizar esta consulta é:


SELECT CLIENTE.nome, CLIENTE.nascimento

FROM CLIENTE

Ou mesmo:


SELECT C.nome, C.nascimento

FROM CLIENTE C
Exemplo 03. Listar o nome e o CPF dos clientes do sexo masculino

SELECT nome, cpf

FROM CLIENTE

WHERE sexo=’masculino’

Neste caso, utilizou-se o filtro sexo=’masculino’ para retornar apenas os indivíduos do sexo masculino.


SELECT nome, cpf

FROM CLIENTE

WHERE sexo=’masculino’

ORDER BY nome DESC
Exemplo 04. Ordenar a listagem anterior por nome, de forma decrescente

Aproveitou-se a solução anterior adicionando-se apenas a cláusula de ordenação de acordo com a descrição do problema.


SELECT nome, salario

FROM CLIENTE

WHERE sexo=’masculino’ and salario <  3000
Exemplo 05. Listar o nome e o salário dos clientes do sexo masculino que ganham menos de R$ 3000

Aqui, tornou-se necessário o uso da expressão lógica de conjunção (and), para poder recuperar os clientes do sexo masculino (sexo=’masculino’) que ganham menos de R$ 3000 (salario < 3000). A expressão lógica (and) faz com que o SGBD retorne apenas as linhas que obedecem as duas condições simultaneamente.

Recuperando informações de várias tabelas

Em diversas situações, existe a necessidade da execução de consultas cujos campos estão localizados em tabelas diferentes. Neste caso, além de declarar as tabelas, é necessário indicar que elas estão relacionadas para que o SGBD possa recuperar as informações de forma coerente. Há duas formas de realizar esta tarefa:

  • Declarar as tabelas na cláusula FROM, indicando o relacionamento na cláusula WHERE, ou;
  • Declarar as tabelas e indicar o tipo de relacionamento na cláusula FROM. Esta abordagem será estudada em outra oportunidade.

Para o Exemplo 06, temos:


SELECT nome, fone

FROM CLIENTE, FONE

WHERE CLIENTE.codigo=FONE.codigo and tipo=’residencial’

Na cláusula FROM, foram declaradas as tabelas que possuem os campos (nome e fone) que devem aparecer no resultado. Na cláusula WHERE, CLIENTE.codigo=FONE.codigo representa o relacionamento entre as tabelas CLIENTE e FONE. Através desse trecho de código o SGBD filtra os registros que correspondem às informações corretas de cada cliente. Já o código tipo=’residencial’ solicita ao SGBD que sejam recuperados apenas os telefones residenciais.

Na realidade, nessas situações o SGBD comumente realiza os seguintes passos:

Execução da operação de produto cartesiano entre as tabelas. Isto significa combinar cada linha da tabela CLIENTE com cada linha da tabela FONE, resultando numa estrutura que possui todas as colunas existentes nas tabelas envolvidas, e quantidade de linhas igual ao produto das linhas de cada tabela (no exemplo, 5 x 5 = 25 linhas). A Figura 1 representa esta situação.

Produto cartesiano entre as tabelas CLIENTE e FONE
Figura 1. Produto cartesiano entre as tabelas CLIENTE e FONE

Remoção das linhas que não correspondem à realidade do banco de dados. Observe que as linhas realçadas em cinza representam informações incorretas. Na prática, devem permanecer na tabela apenas as linhas cujos valores do campo código são idênticos (CLIENTE.codigo=FONE.codigo – linhas marcadas da Figura 1), configurando a situação apresentada na Figura 2.

Estrutura que corresponde à realidade dos dados do banco de dados
Figura 2. Estrutura que corresponde à realidade dos dados do banco de dados

A cláusula tipo=’residencial’ considera apenas os telefones que são do tipo residencial (as linhas marcadas na Figura 2 são descartadas). Neste caso, temos o resultado intermediário apresentado na Figura 3.

Estrutura cujas linhas correspondem aos requisitos (cláusula WHERE) do Exemplo 06
Figura 3. Estrutura cujas linhas correspondem aos requisitos (cláusula WHERE) do Exemplo 06

Finalmente, são mostrados apenas os campos declarados na cláusula SELECT (ver Figura 4).

Resultado final da consulta
Figura 4. Resultado final da consulta

SELECT nome, sexo, fone

FROM CLIENTE, FONE

WHERE CLIENTE.codigo=FONE.codigo and tipo=’celular’
Exemplo 07. Listar o nome, o sexo e o fone celular dos clientes

Esta solução é semelhante à do exemplo 6, sendo adicionado o campo sexo e modificado o campo tipo (tipo=’celular’) para recuperar apenas os clientes que possuem celular.

Nesta parte, foram apresentados diversos exemplos de consultas utilizando a linguagem SQL. Na última parte desse tutorial, estudaremos exemplos mais complexos, envolvendo funções de agregação e subconsultas.

Funções de agregação e elaboração de subconsultas.


SELECT COUNT(*)

FROM CLIENTE
Exemplo 01. Listar a quantidade de clientes

O comando count serve para contabilizar o número de linhas de uma consulta. No exemplo, count(*) retornou o número de linhas da tabela CLIENTE que, nesse contexto, representa o número de clientes.


SELECT COUNT(*)

FROM CLIENTE

WHERE sexo=’feminino’
Exemplo 02. Listar a quantidade de clientes do sexo feminino

Trata-se de uma solução semelhante à do exemplo 1. Apenas foi adicionada a cláusula WHERE com um filtro que recupera as linhas correspondentes às pessoas do sexo feminino (sexo=’feminino’).


SELECT AVG(salario)

FROM CLIENTE
Exemplo 03. Obter a média de salário dos clientes

Esta é uma solução simples. Bastou a utilização da função que calcula a média (avg) a partir de um conjunto de valores (neste caso, o campo salário da tabela CLIENTE). Uma alternativa pode ser vista na Nota 1.

É possível renomear virtualmente qualquer coluna resultante de uma consulta. Este procedimento é útil para deixar o código mais organizado e coerente. Dessa forma, é possível reescrever a solução do Exemplo 03 da seguinte maneira:


SELECT AVG(salario) as MediaSalarial

FROM CLIENTE
Exemplo 04. Obter a média salarial por sexo

SELECT sexo, AVG(salario) as MediaSalarialSexo

FROM   CLIENTE

GROUP BY sexo

Esta solução é semelhante à do exemplo 10. Aqui, foi adicionado o campo (sexo) na cláusula GROUP BY para que o resultado fosse calculado para o sexo masculino e para o feminino.


SELECT

(SELECT COUNT(*) FROM CLIENTES WHERE sexo=’masculino’) AS QtdeHomens,

(SELECT COUNT(*) FROM CLIENTES WHERE sexo=’feminino’) AS QtdeMulheres
Exemplo 05. Mostrar, em uma linha, a quantidade de clientes do sexo masculino e a quantidade de clientes do sexo feminino

O interessante desta solução é que podemos exibir resultados, dos mais simples aos mais complexos, em uma única linha. Para isso, basta declarar um SELECT principal separando, em seguida, por vírgula, cada subconsulta que gera determinada informação.

Praticando subconsultas

No dia-a-dia, os desenvolvedores codificam consultas que não dependem diretamente de alguma tabela, mas do resultado de uma ou de diversas consultas. Este procedimento é comumente chamado de subconsulta. Na prática, o SGBD realiza a subconsulta e o resultado serve como parâmetro de entrada para a consulta principal. Observe os exemplos de 06 a 07.

Note que para sabermos o nome dos clientes sem telefone, é necessário termos certeza de que não existe ocorrência do código do cliente na tabela FONE. Em situações desse tipo, pode-se utilizar o operador (not) in. Observe:


SELECT nome

FROM   CLIENTE

WHERE  codigo not in

(SELECT codigo

FROM FONE)
Exemplo 06. Obter o nome dos clientes que não possuem telefone

Neste caso, o SGBD primeiramente recupera os códigos dos clientes da tabela FONE (SELECT código FROM FONE). Este resultado serve como parâmetro de entrada para a consulta principal, que recupera apenas os clientes sem telefone (clientes cujo código não aparece na subconsulta).


SELECT nome, salario

FROM   CLIENTE

WHERE  salario >

(SELECT avg(salario)

FROM CLIENTE

WHERE SEXO=’MASCULINO’)
Exemplo 07. Obter o nome e o salário dos clientes que ganham mais que a média salarial masculina

Aqui, o SGBD primeiramente calcula a média salarial dos clientes do sexo masculino (subconsulta). O resultado é comparado com o salário de cada cliente, sendo retornadas apenas as informações dos que ganham mais que a média salarial masculina.


SELECT nome

FROM   CLIENTE

WHERE  salario =

(SELECT max(salario)

FROM CLIENTE)
Exemplo 08. Listar o(s) cliente(s) que ganha(m) o maior salário

Neste caso, o SGBD calcula o maior salário através da utilização do operador max na subconsulta (SELECT max(salário) from CLIENTE). Este resultado é comparado com o salário de cada cliente, sendo exibidos apenas os que ganham o correspondente ao maior salário.


SELECT count(*) as QteCliente

FROM   CLIENTE

WHERE  salario >

(SELECT min(salario)

FROM CLIENTE)
Exemplo 09. Verificar quantos clientes ganha(m) mais que o(s) cliente(s) de menor salário

Aqui, a subconsulta recupera o menor salário da tabela CLIENTE. Este salário serve como parâmetro de comparação para a consulta principal, que contabiliza o número de clientes que ganham mais que este salário.


SELECT nome, sexo

FROM   CLIENTE

WHERE  nascimento =

(SELECT max(nascimento)

FROM CLIENTE)
Exemplo 10. Listar o nome e o sexo do cliente mais novo

Observe que neste caso a subconsulta recupera a maior (mais recente) data de nascimento, dentre as cadastradas na tabela CLIENTE. Este resultado serve como parâmetro de entrada para a consulta principal, que retorna o cliente mais novo (podendo ser mais de um cliente).


SELECT nome, sexo

FROM   CLIENTE

WHERE  nascimento =

(SELECT min(nascimento)

FROM CLIENTE)
Exemplo 11. Listar o nome do cliente mais velho

De forma semelhante ao exemplo 10, a subconsulta recupera a data de nascimento mais antiga. Neste caso, o cliente que tiver nascido nesta data, é o que aparecerá no resultado (podendo ser mais de um cliente).

Conclusões

Estudamos neste tutorial os componentes da estrutura utilizada pelos SGBD para o armazenamento dos dados (tabela). Aprendemos que as tabelas são relacionadas através do mecanismo conhecido por chave estrangeira. Vimos também uma sintaxe SQL para consulta aos dados armazenados em um banco de dados, consolidando o aprendizado através de diversos exemplos.

Links Úteis sobre MVC

  • O que é MVC?:

    MVC é atualmente o padrão arquitetural mais utilizado no desenvolvimento web, portanto seu conhecimento é fundamental para a construção de projetos bem estruturados.

  • Spring MVC: Construa aplicações responsivas com Bootstrap:

    Desenvolva aplicações responsivas integrando o framework web da Spring com o Bootstrap, uma das bibliotecas de front-end mais conhecidas.

  • ASP.NET MVC:

    Neste Guia de Referência você encontrará o conteúdo que precisa para aprender a desenvolver aplicações web com o framework ASP.NET MVC e a linguagem C#.

Saiba mais sobre MVC ;)

  • JSF - JavaServer Faces:

    Neste Guia de Referência você encontrará todo o conteúdo que precisa para conhecer o JSF, especificação Java que traz conceitos do padrão MVC e que facilita a construção de interfaces web utilizando componentes.

  • CRUD em PHP e MVC com Busca e Paginação:

    Aprenda a implementar uma busca, paginação e conversão monetária em PHP e MVC.

  • Como implementar o MVC em PHP:

    O padrão MVC é amplamente utilizado no desenvolvimento de aplicações web, e saber implementá-lo é importante para trabalhar de forma eficiente com frameworks como CodeIgniter e Laravel, bem como para desenvolver projetos sem depender dessas soluções de terceiros.