CashPreview 3.0 - Seu Parceiro Financeiro Inteligente
SQL Linguagem Estruturada de ConsultasSQL é uma linguagem de consultas a bancos de dados fácil de ser aprendida para consultas básicas, mas que também tem recursos sofisticados para consultas mais complexas. A versão 3.0 do CashPreview tem no menu "Operações" as opções "Nova consulta SQL" e "Abrir consulta SQL" que servem respectivamente para se criar uma consulta ao banco de dados, executá-la e salvá-la para uso posterior ou para abrir uma consulta previamente criada e comandar a sua execução. A linguagem SQL permite a criação de comandos não apenas para consulta de informações ao banco de dados, mas também para alterar, excluir ou mesmo modificar a estrutura do esquema de armazenamento das informações. As consultas SQL permitidas no CashPreview são apenas as do tipo "SELECT", usadas para consulta de informações. Antes de mais nada, porém, para usar as consultas SQL são necessárias algumas informações básicas. I - Como estão organizadas as informações dentro de um banco de dados? As informações estão organizadas na forma de tabelas. Cada tabela contém múltiplas linhas e múltiplas colunas. Em cada linha de uma tabela temos múltiplas informações sobre um tipo de objeto. Por exemplo, uma tabela de funcionários conterá uma linha para as informações de cada funcionário. Estas linhas são chamadas de registros. Cada registro é dividido em vários campos. Os campos são usados para conterem unidades de informações. Por exemplo, teremos o campo "Nome" para conter a informação do nome do funcionário, o campo "Codigo" para conter um código associado ao funcionário, que o identifica de modo único no banco de dados. E já que estamos falando de tabelas, os campos também são chamados de colunas. Portanto, no cruzamento da coluna "Nome" com as linhas (registros) da tabela Funcionarios, teremos os nomes de todos os funcionários. Veja graficamente abaixo: Tabela Funcionarios
Além de um nome para identificá-los, os campos de uma tabela possuem informação de tamanho e de tipo de dados, que servem para identificar como os dados estão armazenados nos campos. Os tipos de dados podem ser: númerico, data, texto, booleano, etc. Vale aqui dizer que os campos do tipo booleano são usados para receber apenas dois tipos de valores: verdadeiro ou falso. As palavras reservadas TRUE e FALSE representam respectivamente verdadeiro e false na linguagem SQL e, nos bancos de dados do Access, estes valores podem ser interpretados numericamente como -1 e 0. Quando um campo é definido durante a criação de uma tabela, pode-se definir um valor padrão para este campo no caso de ele não ser informado na inclusão de um novo registro na tabela. Para exemplificar, se tivessemos o campo Inativo do tipo booleano na tabela de Funcionarios, poderiamos definir o valor padrão para este campo em FALSE, pois, ao incluir um novo funcionário, este valor seria assumido por padrão, mesmo que não fosse informado. Caso não se tenha nenhuma definição de valor padrão para o campo e ele não seja informado, o valor NULL será assumido. NULL é uma palavra reservada do SQL que veremos mais adiante como usá-la para testarmos se um campo contém ou não alguma informação armazenada. Dentro de um banco de dados, podemos ter múltiplas tabelas e estas podem estar relacionadas entre si por um ou mais campos contendo informações em comum. Sabemos que uma tabela real de funcionários teria muito mais informações do que simplesmente o código e o nome de cada funcionário. Por exemplo, teríamos também informação sobre o cargo ocupado pelo funcionário. Neste caso, o cargo seria representado não pelo nome do cargo, mas por um código numérico que identificasse o cargo. Porém, onde estaria o nome do cargo quando quisessemos conhecê-lo? Estaria numa tabela "Cargos". Na tabela "Cargos" poderiamos ter um código que identificaria o cargo, o nome do cargo, o salário atribuido ao cargo, etc. Veja um exemplo da tabela "Cargos" abaixo: Tabela Cargos
Supondo que tenhamos o campo CodigoCargo na tabela de funcionários, ela poderia ser assim: Tabela Funcionarios
Há várias vantagens em se usar o código do cargo e não o nome do cargo na tabela de funcionários. Uma delas é que o nome do cargo pode mudar na tabela Cargos sem que nada precise mudar na tabela Funcionarios, pois lá temos apenas o código do cargo, que permanece fixo. Outra vantagem é que a tabela Cargos pode conter muito mais informações relativas a cada cargo do que apenas o nome. A presença do código do cargo na tabela Funcionarios relaciona cada registro de funcionário a todas as informações do seu cargo que se encontram na tabela Cargos. Se quisessemos listar a tabela de funcionários e mais o nome do cargo e salário de cada um, teríamos que fazer uma consulta que coletasse informações tanto da tabela Funcionarios como da tabela Cargos. Isto seria feito cruzando as duas tabelas pelo campo CodigoCargo e resultaria em algo assim:
Apenas antecipando o que veremos mais adiante, o texto de uma consulta SQL para retornar as informações acima poderia ser escrito assim: SELECT F.*, C.Cargo, C.Salario FROM Funcionarios As F, Cargos As C WHERE F.CodigoCargo = C.CodigoCargo; A instrução acima instrui o banco de dados para retornar um conjunto de registros com todos os campos da tabela Funcionarios (aqui apelidada de F) que tenham o campo CodigoCargo igual ao campo CodigoCargo na tabela Cargos (aqui apelidada de C). Além disto, instrui para que sejam juntadas às informações de cada funcionário o nome de cargo e salário extraidos da tabela Cargos correspondentes ao código de cargo do funcionário. Veremos, a seguir, toda a lógica da sintaxe desta consulta e das instruções SELECT em geral. II - Sintaxe das instruções SELECT O seguinte esquema mostra todos os elementos sintáticos de uma instrução SELECT. SELECT [predicado { * | tabela.* | [tabela.]campo1 [AS alias1] [, [tabela.]campo2 [AS alias2] [, ...]]} FROM expressãotabela [, ...] [IN bancodedadosexterno] [WHERE... ] [GROUP BY... ] [HAVING... ] [ORDER BY... ] No esquema acima, as palavras em letras maiúsculas são palavras reservadas da linguagem SQL que têm funções específicas na instrução SELECT. Uma consulta de seleção de registros começa sempre pela palavra SELECT. A plavra FROM indica a origem dos dados a serem retornados. Pode ser uma sequência de nomes de tabelas separadas por vírgulas ou mesmo subconsultas também separadas por vírgulas. Exemplo: SELECT F.*, C.Cargo, C.Salario FROM Funcionarios AS F, Cargos AS C WHERE F.CodigoCargo = C.CodigoCargo; SELECT F.*, C.Cargo, C.Salario FROM Funcionarios AS F, (SELECT CodigoCargo, Cargo, Salario FROM Cargos) AS C WHERE F.CodigoCargo = C.CodigoCargo; No primeiro exemplo acima, as tabelas Funcionarios e Cargos foram renomeadas (apelidadas) internamente usando a expressão AS para F e C respectivamente. Esta técnica se mostra útil quando se tem campos de mesmos nomes em ambas as tabelas ou subconsultas e se quer determinar exatamente qual deve ser retornado. A forma de identificar a qual campo de qual tabela estamos nos referindo é usar o apelido dado à tabela seguido de um ponto e do nome do campo, exemplo: F.CodigoCargo. Poderiamos usar o nome da tabela em lugar do seu apelido, mas apelidar a tabela por uma simples letra facilita a escrita dentro da consulta. No segundo exemplo, tivemos os dados buscados na tabela Funcionarios e numa subconsulta à tabela Cargos. Este segundo exemplo não é prático, pois obteríamos o mesmo resultado usando a simplicidade do primeiro, mas serve para exemplificar a possibilidade de se embutir uma consulta SQL dentro de outra. A palavra WHERE é usada para indicar qual será o critério a ser usado na consulta. Após esta palavra, incluimos as condições que irão filtrar os registros do universo total existente nas tabelas envolvidas na consulta. Os critérios podem ser construídos usando operadores de comparação entre os campos existentes nas tabelas ou mesmo com um valor determinado. Nos exemplos usados acima, o critério foi apenas o da comparação entre os campos CodigoCargo da tabela de funcionários com o campo CodigoCargo da tabela Cargos, mas poderia se estender além disto. Poderia ser, por exemplo: F.CodigoCargo = C.CodigoCargo AND F.Nome = 'Paulo Ferreira' AND F.Inativo = FALSE. Observe, neste exemplo, que informações definidas no banco de dados como sendo do tipo texto, tais como nomes, números de telefones, endereços, devem estar entre aspas simples nas consultas SQL para bancos de dados Access. Neste exemplo, o campo Inativo da tabela Funcionarios (F) é do tipo booleano e por isto é testado para um valor booleano (FALSE). Neste caso, temos um critério que compara os campos CodigoCargo presentes nas duas tabelas, mas também busca apenas os funcionários que tenham o nome 'Paulo Ferreira' e que não estejam inativos. Observe que estes três critérios foram unidos pela palavra AND, que significa "e" em inglês. AND cumpre a função de um operador lógico, que fará com que o critério somente seja satisfeito para os registros que cumprirem a todas as condições de comparação. Mas também poderíamos usar a palavra OR, que significa "ou" em inglês. OR cumpre a função do operador lógico "ou inclusivo", ou seja, seriam retornados todos os registros que cumprissem ao menos uma de duas condições ou ambas. Além de AND e OR, também é possível usar o operador NOT para negar uma condição de comparação. Caso quisessemos cruzar a tabela Funcionarios com a tabela Cargos como fizemos acima, porém retornando apenas os registros em que o nome do funcionário fosse diferente de 'Paulo Ferreira', criaríamos um critério assim: F.CodigoCargo = C.CodigoCargo AND NOT F.Nome = 'Paulo Ferreira'. Como operadores de comparação podemos usar também >, <, >=, <= e as palavras reservadas BETWEEN ... AND ... Esta última para especificar que desejamos apenas o que estiver dentro de um certo intervalo de valores. Exemplo: Data BETWEEN #12/31/2007# AND #01/31/2008# . Observe neste exemplo que, com bancos de dados Access, os valores de datas no SQL devem sempre ser informados entre sinais de # e o mês deve preceder o dia na expressão da data. Uma outra palavra reservada também é usada no Access para a criação de critérios que testam os valores dos campos para verificar se estão em NULL. Trata-se da palavra IS. No Access, para testar se um campo está com valor nulo usamos a expressão IS NULL e nunca = NULL. Exemplo: F.CodigoCargo = C.CodigoCargo AND NOT C.Salario IS NULL . A cláusula GROUP BY... e as funções agregadas A linguagem SQL nos fornece algumas funções que usamos para retornar contagens, somatórias, médias, máximos e mínimos, valores estatísticos calculados com base nos valores de campos das tabelas. Veja abaixo as mais comuns:
Exemplos de consultas completas usando as funções acima: SELECT MAX (Salario) AS Maior_Salario FROM Cargos WHERE DataDeCriacao BETWEEN #01/31/2007# AND #12/31/2007# SELECT COUNT(*) AS Total_de_Recepcionistas FROM Funcionarios WHERE CodigoCargo = 2 Note que nos exemplos acima a consulta retornará apenas um registro, pois a totalização se referirá ao conjunto de todos os registros que satisfaçam ao critério da cláusula WHERE . Suponhamos que quisessemos algo mais detalhado, como por exemplo, a contagem de quantos funcionários temos por cada cargo. Neste caso, usariamos a cláusula GROUP BY para agruparmos a contagem por cargo e teríamos uma consulta assim: SELECT CodigoCargo, COUNT( *) AS Total_de_Funcionarios FROM Funcionarios GROUP BY CodigoCargo Neste caso, teríamos como retorno um registro para cada código de cargo e o total de funcionários em cada cargo conforme abaixo:
O uso da cláusula GROUP BY faz com que os registros sejam retornados na ordem crescente do(s) campo(s) usado(s) para agrupar o resultado da função agregada. Mais um detalhe, todos os campos na cláusula SELECT devem aparecer após a cláusula GROUP BY separados por vírgula, ou você terá um erro de sintaxe na consulta. A cláusula HAVING ... A cláusula HAVING vem a complementar a cláusula GROUP BY . Quando usamos GROUP BY , os registros retornados serão todos os que satisfizerem ao critério informado após a palavra WHERE . Porém, podemos querer fazer uma segunda filtragem após termos os resultados dos cálculos das funções agregadas. Neste caso, usamos a cláusula HAVING para fazer esta filtragem posterior. Exemplo: SELECT CodigoCargo, COUNT(*) AS Total_de_Funcionarios FROM Funcionarios GROUP BY CodigoCargo HAVING COUNT(*) >= 4 No exemplo acima, queremos que sejam retornados apenas os registros de códigos de cargos que tenham a contagem de funcionários superior ou igual a 4 funcionários. Usando ORDER BY... para ordenar os registros retornados A cláusula opcional ORDER BY é usada para definir o critério de ordenação dos registros resultantes da consulta. Tem precedência sobre a ordenação automática produzida quando se usa a cláusula GROUP BY. A ordenação é especificada pela lista dos campos segundo os quais será feita a ordenação e na ordem decrescente de precedência de uns sobre os demais. Por padrão a ordenação é ascendente, mas pode ser modificada usando-se as palavras ASC e DESC após os campos conforme a ordenação que será feita através dos seus valores. Exemplo: SELECT Sobrenome, Nome FROM Funcionarios ORDER BY Sobrenome, Nome DESC Acima, ordenamos uma consulta à tabela Funcionarios de modo a ter os registros em ordem crescente por sobrenome e em ordem decrescente por nome. As demais partes do esquema de sintaxe da consulta SELECT já apresentado antes estão descritas abaixo:
Consultas de União Uma outra forma de se combinar consultas além de se embutir uma dentro de outra, como vimos acima, é criar uma união de consultas. Usando a palavra UNION podemos unir várias consultas SQL e obter os registros retornados por cada uma*. A condição para que possamos fazer isto é que todas as consultas retornem o mesmo número de campos, com os mesmos nomes ou apelidos e na mesma ordem dentro da consulta. Exemplo: (SELECT CodConta, Data, Valor From Lancamentos) UNION (SELECT CodConta, Data, Valor From HistoricosDeLancamentos) ORDER BY Data; Um detalhe importante a saber sobre as consultas de união é que elas sempre retornam um conjunto de registros exclusivos, ou seja, se em uma ou mais consultas houver mais de um registro com todos os campos iguais, apenas um deles será retornado. Para que mesmo os registros repetidos possam ser retornados, devemos usar o predicado ALL após cada palavra UNION ligando as consultas. Para que todos os registros fossem retornados, o exemplo acima ficaria assim: (SELECT CodConta, Data, Valor From Lancamentos) UNION ALL (SELECT CodConta, Data, Valor From HistoricosDeLancamentos) ORDER BY Data; Consultas parametrizadas Além do que já foi exposto acima, as consultas SQL também podem ser parametrizadas, isto é, podem conter variáveis que são definidas antes de cada execução para determinar os critérios da execução da consulta. Veja mais sobre isto em " A cláusula PARAMETERS ".
|