Manuais e recursos para desenvolvimento web www.criarweb.com
Tutorial de SQL
Autores do manual Este manual foi criado pelos seguintes colaboradores de Criarweb.com: Rubén Alvarez
Paulino Michelazzo
Fabio Correa
Glaucio Guerra
Eber M. Duarte
Miguel Angel Alvarez Tradução de JML
(11 capítulos)
http://www.devmedia.com.br (1 capítulo)
Rosendo Lopez Robles
(1 capítulo)
Alfredo Lotar (1 capítulo)
http://www.devmedia.com.br (1 capítulo)
http://www.devmedia.com.br (1 capítulo)
Agustin Jareño
http://www.devmedia.com.br (1 capítulo)
(1 capítulo)
Claudio
(12 capítulos)
http://personal.lobocom.es/claudio/ (15 capítulos)
Jonathan Soriano Folch
Pol Salvat
(1 capítulo)
http://www.mistrucos.net (1 capítulo)
Sara Alvarez Langa (1 capítulo)
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
1
Manuais e recursos para desenvolvimento web www.criarweb.com
O que é SQL As aplicações em rede são cada dia mais numerosas e versáteis. Em muitos casos, o esquema básico de operação é uma série de scripts que dirigem o comportamento de uma base de dados. Devido à diversidade de linguagens e de base de dados existentes, a maneira de comunicar entre umas e outras seria realmente complicado de providenciar, providenciar, a não ser pela pe la existência de padrões que nos permite realizar as operações básicas de una forma universal. É justamente disso que se trata o Structured Query Language que não é mais do que uma linguagem padrão de comunicação com base de dados. Falamos portanto, de uma linguagem normalizada que nos permite trabalhar com qualquer tipo de linguagem (ASP ou PHP) em combinação com qualquer tipo de base de dados (MS Access, SQL Server, Server, MySQL...). O fato de ser padrão não quer dizer que seja idêntico para cada base de dados. Na prática, determinadas bases de dados implementam funções específicas que não têm necessariamente que funcionar em outras. À parte desta universalidade, o SQL possui outras duas características muito apreciadas. Por Por uma parte, apresenta potência e versatilidade notáveis que contrasta, por outra, com sua acessibilidade de aprendizagem. Rubén Alvarez Artigo por por Rubén
Tipos de campos Como sabemos, um banco de dados é composto por tabelas onde armazenamos registros catalogados em função de diferentes campos (características). Um aspecto prévio a considerar é a natureza dos valores que introduzimos nesses campos. Visto que um banco de dados trabalha com todo o tipo de informações, é importante especificar que tipo de valor estamos introduzindo de maneira a, por um lado, facilitar a busca posteriormente e por outro, otimizar os recursos de memória. Cada banco de dados introduz tipos de valores de campo que não necessariamente estão presentes em outros. Entretanto, existe um conjunto de tipos que estão representados na totalidade destes bancos. Estes tipos comuns são os seguintes: Alfanuméricos
Contém cifras e letras. Apresentam uma longitude limitada (255 caracteres)
Numéricos
Existem de vários tipos, principalmente, inteiros (sem decimais) e reais (com decimais).
Booleanos
Possuem duas formas: Verdadeiro e falso (Sim ou Não)
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
2
Manuais e recursos para desenvolvimento web www.criarweb.com
O que é SQL As aplicações em rede são cada dia mais numerosas e versáteis. Em muitos casos, o esquema básico de operação é uma série de scripts que dirigem o comportamento de uma base de dados. Devido à diversidade de linguagens e de base de dados existentes, a maneira de comunicar entre umas e outras seria realmente complicado de providenciar, providenciar, a não ser pela pe la existência de padrões que nos permite realizar as operações básicas de una forma universal. É justamente disso que se trata o Structured Query Language que não é mais do que uma linguagem padrão de comunicação com base de dados. Falamos portanto, de uma linguagem normalizada que nos permite trabalhar com qualquer tipo de linguagem (ASP ou PHP) em combinação com qualquer tipo de base de dados (MS Access, SQL Server, Server, MySQL...). O fato de ser padrão não quer dizer que seja idêntico para cada base de dados. Na prática, determinadas bases de dados implementam funções específicas que não têm necessariamente que funcionar em outras. À parte desta universalidade, o SQL possui outras duas características muito apreciadas. Por Por uma parte, apresenta potência e versatilidade notáveis que contrasta, por outra, com sua acessibilidade de aprendizagem. Rubén Alvarez Artigo por por Rubén
Tipos de campos Como sabemos, um banco de dados é composto por tabelas onde armazenamos registros catalogados em função de diferentes campos (características). Um aspecto prévio a considerar é a natureza dos valores que introduzimos nesses campos. Visto que um banco de dados trabalha com todo o tipo de informações, é importante especificar que tipo de valor estamos introduzindo de maneira a, por um lado, facilitar a busca posteriormente e por outro, otimizar os recursos de memória. Cada banco de dados introduz tipos de valores de campo que não necessariamente estão presentes em outros. Entretanto, existe um conjunto de tipos que estão representados na totalidade destes bancos. Estes tipos comuns são os seguintes: Alfanuméricos
Contém cifras e letras. Apresentam uma longitude limitada (255 caracteres)
Numéricos
Existem de vários tipos, principalmente, inteiros (sem decimais) e reais (com decimais).
Booleanos
Possuem duas formas: Verdadeiro e falso (Sim ou Não)
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
2
Manuais e recursos para desenvolvimento web www.criarweb.com
Datas
Memos
Armazenam datas facilitando posteriormente sua exploração. Armazenar datas desta forma possibilita ordenar os registros por datas ou calcular os dias entre uma data e outra... São campos alfanuméricos de longitude ilimitada. Apresentam o inconveniente de não poder ser indexados (veremos mais adiante o que isto quer dizer).
São campos numéricos inteiros que incrementam em uma unidade seu Autoincrementáveis valor para cada registro incorporado. Sua utilidade é mais que evidente: Servir de identificador já que q ue são exclusivos de um registro.
Artigo por Rubén por Rubén Alvarez
Adicionar um novo registro Os registros podem ser introduzidos a partir de sentenças que empregam a instrução Insert. A sintaxe utilizada é a seguinte: Insert Into nome_tabela (nome_campo1, nome_campo2,...) Values (valor_campo1, (valor_campo1, valor_campo2...) Um exemplo simples a partir da nossa tabela modelo é a introdução de um novo cliente que seria feito com uma instrução deste tipo: Insert Into clientes (nome, sobrenomes, endereço, cidade, código postal, e-mail, pedidos) Values ('Pedro', ('Pedro', 'Palotes', 'Percebe n°13', 'Londrina', '123456', '
[email protected]', 33) Como se pode ver, ver, os campos não numéricos ou booleanos vão delimitados por apóstrofes: '. Também é interessante ver que o código postal foi salvo como um campo não numérico. Isto é devido a que em determinados países (Inglaterra,por exemplo) os códigos postais contém também letras. Nota: Se desejarmos praticar com um banco de dados que está vazio, primeiro devemos criar as tabelas que vamos preencher. preencher. As tabelas também se criam com sentenças SQL e aprendemos a fazer isso no último capítulo. capítulo. Embora, de qualquer forma, pode ser que seja mais cômodo utilizar um programa com interface gráfica, como Access, que pode nos servir para criar as tabelas em banco de dados do próprio Access ou por ODBC a outros bancos de dados como SQL Server ou MySQL MySQL,, por dar dois exemplos. Outra possibilidade em um banco de dados como MySQL, seria criar as tabelas utilizando um software como PhpMyAdmin PhpMyAdmin..
Obviamente, não é imprescindível preencher todos os campos do registro. Porém, poder ser que determinados campos sejam necessários. Estes campos necessários podem ser definidos de finidos quando construirmos nossa tabela mediante o banco de dados. Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
3
Manuais e recursos para desenvolvimento web www.criarweb.com
Nota: Se não inserirmos um dos campos no banco de dados se iniciará com o valor padrão que tivermos definido na hora de criar a tabela. Se não houver um valor padrão, provavelmente se inicie como NULL (vazio), no caso de que este campo permita valores nulos. Se esse campo não permitir valores nulos (isso se define também ao criar a tabela) o mais seguro é que a e xecução da sentença SQL nos dê um erro.
É muito interessante, já veremos mais adiante o porquê, o introduzir durante a criação de nossa tabela um campo auto-incrementável que nos permita atribuir um único número a cada um dos registros. Deste modo, nossa tabela clientes apresentaría para cada registro um número exclusivo do cliente que será muito útil quando consultarmos várias tabelas simultaneamente. Artigo por Rubén Alvarez
Apagar um registro Para apagar um registro nos servimos da instrução Delete. Neste caso devemos especificar qual ou quais são os registros que queremos apagar. Por isso, é necessário estabelecer uma seleção que se realize mediante a cláusula Where. A forma de selecionar será vista; detalhadamente em capítulos posteriores. Agora, nos contentaremos em mostrar qual é o tipo de sintaxe utilizada para efetuar estas supressões: Delete From nome_tabela Where condicoes_de_selecao Nota: Se desejarmos praticar com um banco de dados que estiver vazio, primeiro devemos criar as tabelas que vamos preencher. As tabelas também se criam com sentenças SQL que aprendemos a fazer no último capítulo.
Se quisermos, por exemplo, apagar todos os registros dos clientes que se chamarem Pedro, faríamos da seguinte forma: Delete From clientes Where nome='Pedro' Temos que ter cuidado com esta instrução, pois se não especificarmos uma condição com Where, o que estamos fazendo é apagar toda a tabela: Delete From clientes Artigo por Rubén Alvarez
Atualizar um registro Update é a instrução que nos serve para modificar nossos registros. Como para o caso de Delete, necessitamos especificar por meio de Where quais são os registros que queremos fazer efetivas nossas modificações. Ademais, obviamente, teremos que especificar quais são os Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
4
Manuais e recursos para desenvolvimento web www.criarweb.com
novos valores dos campos que desejamos atualizar. A sintaxe é deste tipo: Update nome_tabela Set nome_campo1 = valor_campo1, nome_campo2 = valor_campo2,... Where condicoes_de_selecao Um exemplo aplicado: Update clientes Set nome='José' Where nome='Pedro' Mediante esta sentença mudamos o nome Pedro por José em todos os registros cujo nome seja Pedro. Aqui também há que ser cuidadoso de não esquecer de usar Where, do contrário, modificaríamos todos os registros de nossa tabela. Artigo por Rubén Alvarez
Seleção de tabelas I A seleção total ou parcial de uma tabela se realiza mediante a instrução Select. Em tal seleção há que especificar: -Os campos que queremos selecionar -A tabela na qual fazemos a seleção Em nossa tabela modelo de clientes poderíamos fazer, por exemplo, uma seleção do nome e endereço dos clientes com uma instrução deste tipo: Select nome, endereço From clientes Se quiséssemos selecionar todos os campos, ou seja, toda a tabela, poderíamos utilizar o asterisco * da seguinte forma: Select * From clientes Também é muito útil filtrar os registros mediante condições que vêem expressas depois da cláusula Where. Se quiséssemos mostrar os clientes de uma determinada cidade usaríamos uma expressão como esta: Select * From clientes Where cidade Like 'Rio de janeiro' Ademais, poderíamos ordenar os resultados em função de um ou vários de seus campos. Para este último exemplo poderíamos ordená-los por nome assim: Select * From clientes Where cidade Like 'Rio de janeiro' Order By nome Tendo em conta que pode haver mais de um cliente com o esmo nome, poderíamos dar um segundo critério que poderia ser o sobrenome: Select * From clientes Where cidade Like 'Rio de Janeiro' Order By nome, sobrenome Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
5
Manuais e recursos para desenvolvimento web www.criarweb.com
Se invertêssemos a ordem " nome,sobrenome " por " sobrenome, nome ", o resultado seria diferente. Teríamos os clientes ordenados por sobrenome e aqueles que tivessem sobrenomes idênticos se sub-classificariam pelo nome. É possível também classificar por ordem inversa. Se por exemplo quiséssemos ver nossos clientes por ordem de pedidos realizados tendo aos maiores em primeiro lugar escreveríamos algo assim: Select * From clientes Order By pedidos Decres Uma opção interessante é a de efetuar seleções sem coincidência. Se por exemplo, buscássemos saber em que cidades se encontram nossos clientes sem a necessidade de que para isso apareça várias vezes a mesma cidade, usaríamos uma sentença desta classe: Select Distinct cidade From clientes Order By cidade Assim evitaríamos ver repetido Rio de Janeiro tantas vezes quantos clientes tivermos nessa cidade. Artigo por Rubén Alvarez
Seleção de tabelas II Quisemos compilar na forma de tabela certos operadores que podem ser úteis em determinados casos. Estes operadores serão utilizados depois da cláusula Where e podem ser combinados habilmente mediante parênteses para otimizar nossa seleção a níveis bastante altos. Operadores matemáticos: >
Maior que
<
Menor que
>= Maior ou igual que <= Menor ou igual que <> Diferente =
Igual
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
6
Manuais e recursos para desenvolvimento web www.criarweb.com
Operadores lógicos And Or Not
Outros operadores Like
Seleciona os registros cujo valor de campo se assemelhe, não tendo em conta maiúsculas e minúsculas.
In e Not In
Dá um conjunto de valores para um campo para os quais a condição de seleção é (ou não) válida
Is Null e Is Not Null
Seleciona aqueles registros onde o campo especificado está (ou não) vazio.
Between...A Seleciona os registros compreendidos em um intervalo nd Distinct
Seleciona os registros não coincidentes
Desc
Classifica os registros por ordem inversa
Curingas * Substitui a todos os campos % Substitui a qualquer coisa ou nada dentro de uma cadeia _ Substitui só um caractere dentro de uma cadeia
Vejamos a seguir aplicações práticas destes operadores. Nesta sentença selecionamos todos os clientes de Salvador cujo nome não seja Jose. Como se Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
7
Manuais e recursos para desenvolvimento web www.criarweb.com
pode ver, empregamos Like ao invés de = simplesmente para evitar inconvenientes devido ao emprego ou não de maiúsculas. Select * From clientes Where cidade Like 'salvador' And Not nome Like 'Jose' Se quiséssemos recolher em uma seleção aos clientes de nossa tabela cujo sobrenome começa por A e cujo número de pedidos esteja compreendido entre 20 e 40: Select * From clientes Where sobrenomes like 'A%' And pedidos Between 20 And 40 O operador In, será visto mais adiante, é muito prático para consultas em várias tabelas. Para casos em uma única tabela é empregada da seguinte forma: Select * From clientes Where cidade In ('Salvador','Fortaleza','Florianopolis') Desta forma selecionamos aqueles clientes que vivem nessas três cidades. Artigo por Rubén Alvarez
Seleção de tabelas III Um banco de dados pode ser considerado como um conjunto de tabelas. Estas tabelas, em muitos casos, estão relacionadas entre elas e se complementam unas com outras. Fazendo referência ao nosso clássico exemplo de um banco de dados para uma aplicação de ecomercio, a tabela clientes que estivemos falando pode estar perfeitamente coordenada com uma tabela onde armazenamos os pedidos realizados por cada cliente. Esta tabela de pedidos pode por sua vez, estar conectada com uma tabela onde armazenamos os dados correspondentes a cada artigo do inventário. Deste modo poderíamos facilmente obter informações contidas nessas três tabelas como pode ser a designação do artigo mais popular em uma determinada região onde a designação do artigo seria obtida na tabela de artigos, a popularidade (quantidade de vezes que esse artigo foi vendido) viria da tabela de pedidos e a região estaria compreendida obviamente na tabela clientes. Este tipo de organização baseada em múltiplas tabelas conectadas nos permite trabalhar com tabelas muito mais manejáveis e ao mesmo tempo, nos evita copiar o mesmo campo em vários lugares já que podemos acessa-lo a partir de uma simples chamada à tabela que o contém.
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
8
Manuais e recursos para desenvolvimento web www.criarweb.com
Neste capítulo veremos como, usando o que foi aprendido até agora, podemos realizar facilmente seleções sobre várias tabelas. Definiremos antes de nada as diferentes tabelas e campos que vamos utilizar em nossos exemplos: Tabela de clientes Nome campo
Tipo campo
id_cliente
Numérico inteiro
nome
Texto
sobrenomes
Texto
endereço
Texto
cidade
Texto
cep
Texto
telefone
Numérico inteiro
email
Texto
Tabela de pedidos Nome campo
Tipo campo
id_pedido
Numérico inteiro
id_cliente
Numérico inteiro
id_artigo
Numérico inteiro
data
Data
quantidade
Numérico inteiro
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
9
Manuais e recursos para desenvolvimento web www.criarweb.com
Tabela de artigos Nome campo
Tipo campo
id_a _art rtig igo o
Numéric rico inteiro
titulo
Alfanumérico
autor
Alfanumérico
editorial
Alfanumérico
preço
Numérico real
Estas tabelas podem ser utilizadas simultaneamente para extrair informações de todo tipo. Suponhamos que queremos enviar um mailing a todos aqueles que tiverem realizado um pedido nesse mesmo dia. Poderíamos escrever algo assim: Select clientes.sobrenomes, clientes.email From clientes,pedidos Where pedidos.data like '25/02/00' And pedidos.id_cliente= clientes.id_cliente Como pode ser visto desta de sta vez, depois da cláusula From, introduzimos o nome das duas tabelas de onde tiramos as informações. Ademais, o nome de cada campo vai precedido da tabela de proveniência separado ambos por um ponto. Nos campos que possuem um nome que só aparece em uma das tabelas, não é necessário especificar sua origem embora na hora de ler sua sentença possa ser mais claro tendo esta informação mais precisa. Neste caso, o campo data poderia ter sido designado como "data" ao invés de "pedidos.data". "pedido s.data". Vejamos outro exemplo mais para consolidar estes novos conceitos. Desta vez queremos ver o título do livro correspondente a cada um dos pedidos realizados: Select pedidos.id_pedido, artigos.titulo From pedidos, artigos Where pedidos.id_artigo=artigos.id_artigo Na verdade a filosofia continua sendo a mesma que para a consulta de uma única tabela. Artigo por Rubén por Rubén Alvarez
Seleção de tabelas IV Além dos critérios até agora explicados para realizar as consultas em tabelas, SQL permite também aplicar um conjunto de funções pré-definidas. pré -definidas. Estas funções, embora sejam básicas, Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
10
Manuais e recursos para desenvolvimento web www.criarweb.com
podem nos ajudar em alguns momentos a expressar nossa seleção de uma maneira mais simples sem ter que recorrer a operações adicionais por parte do script que estivermos executando. Algumas destas funções são representadas na seguinte tabela: Função
Descrição
Soma(campo) Calcula a soma dos registros do campo campo especificado Avg(Campo) Avg(Campo) Calcula Calcula a média dos dos registros registros do campo campo especifica especificado do Count(*)
Proporciona o valor do número de registros que foram selecionados
Max(Campo) Max(Campo) Indica qual é o valor valor máximo máximo do campo campo Min(Campo) Min(Campo) Indica qual é o valor valor mínimo mínimo do campo
Dado que o campo da função não existe no banco de dados, pois o estamos gerando virtualmente, isto pode criar inconvenientes quando estivermos trabalhando com nossos scripts na hora de tratar seu valor e seu nome de campo. É por isso que o valor da função tem que ser recuperada a partir de um apelido que nós especificaremos na sentença SQL a partir da instrução AS. AS. A coisa poderia ficar assim: Select Soma(total) As soma_pedidos From pedidos A partir desta sentença calculamos a soma dos valores de todos os pedidos realizados e armazenamos esse valor em um campo virtual chamado soma_pedidos que poderá po derá ser utilizado como qualquer outro campo por nossas páginas dinâmicas. Obviamente, tudo que foi visto até agora pode ser aplicado neste tipo de funções de modo que, por exemplo, podemos estabelecer condições com a cláusula Where construindo sentenças como esta: Select Soma(quantidade) as soma_artigos From pedidos Where id_artigo=6 Isto nos proporcionaria a quantidade de exemplares de um determinado livro que foram vendidos. vendidos. Outra propriedade interessante destas funções é que permitem realizar operações com vários campos dentro de um mesmo parênteses: parênteses: Select Avg(total/quantidade) From pedidos Esta sentença dá como resultado o preço médio que estão sendo vendidos os livros. livros. Este resultado não tem porquê coincidir com o do preço médio dos livros presentes no Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
11
Manuais e recursos para desenvolvimento web www.criarweb.com
inventário, inventário, já que, pode ser que as pessoas tenham tendência a comprar os livros caros ou os baratos: Select Avg(precio) as preco_venda From artigos Uma cláusula interessante no uso das funções é Group By. By. Esta cláusula nos permite agrupar registros aos quais vamos aplicar a função. Podemos por exemplo calcular o dinheiro gastado por cada cliente: cliente : Select id_cliente, Soma(total) as soma_pedidos From pedidos Group By id_cliente Ou saber o número de pedidos que foram realizados: realizados: Select id_cliente, Count(*) as numero_pedidos From pedidos Group By id_cliente As possibilidades como vemos são numerosas e pode ser práticas. Agora tudo fica à disposição de nossas ocorrências e imaginação. Artigo por Rubén por Rubén Alvarez
Aproveite seu banco de dados Bancos de dados deixaram há muito de ser simplesmente um repositório de informações usados para, no máximo, organizar registros de tal forma que posteriormente pudessem ser indexados e/ou recuperados de alguma forma. Hoje eles são ferramentas poderosas nas tomadas de decisões dentro das empresas empre sas que, aproveitando-se da grande quantidade de dados lá existentes, extraem análises de vários tipos para executarem os próximos movimentos e ações em seus mercados. Mas o banco de dados por sí não opera milagres. É necessária a presença de um profissional conhecedor de suas ferramentas e entranhas para tirar dele tudo aquilo que é possível. Este profissional normalmente conhecido por DBA (Database Administrator) é a peça fundamental neste processo. Por outro lado, os desenvolvedores de software mesmo não sendo especialistas em bancos de dados como os DBA's, podem (e devem) aproveitar um pouco do que é oferecido por estas ferramentas para criar aplicações mais rápidas, mais enxutas e mais “limpas”, “limpas”, aproveitando funções existentes mas que na maioria das vezes são esquecidas no momento do desenvolvimento. Sobre isso que vamos falar hoje: aproveitamento de funções de bancos de dados. Obs: neste artigo usarei exemplos com o banco de dados MySQL e a linguagem PHP. PHP. Entretanto com toda a certeza eles e les podem ser usados também com outras bases e linguagens de forma semelheante. Somando valores, e concatenando campos Com uma frequência impressionante, precisamos somar valores vindos de uma base de dados. Para fazer isso dentro do código do programa, podemos ter:
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
12
Manuais e recursos para desenvolvimento web www.criarweb.com
$Rst = mysql_query("SELECT valor FROM tabela",$conexao); while($valor=mysql_fetch_row($Rst)){ $resultado = $resultado + $valor[0]; } print $resultado;
Mas, que tal assim: $Rst = mysql_fetch_row(mysql_query("SELECT SUM(valor) FROM tabela", $conexao)); print $Rst[0];
Hmmm... de 5 linhas para duas? Mas como? O “segredo” está na função SUM usada na segunda instrução. Ela simplesmente soma os valores do campo e reduz um laço dentro do código. Com isso temos mais eficiência, velocidade e código limpo. Um outro exemplo interessante pode ser visto quando, por exemplo, precisamos concatenar (unir) dois campos. Para criar uma tabela no código, faríamos assim: $Rst = mysql_query("SELECT nome, sobrenome FROM tabela",$conexao); while($valor=mysql_fetch_row($Rst)){ echo 'Nome Completo: '.$valor[0].$valor[1].'
'; }
Mas também pode ser feito assim: $Rst = mysql_query("SELECT CONCAT(nome, sobrenome) FROM tabela", $conexao); while($valor=mysql_fetch_row($Rst)){ echo 'Nome Completo: '.$valor[0].'
'; }
Observe que não temos redução de linhas mas de caracteres que deixam o código mais limpo e aproveitamos o processamento do banco ao invés do servidor web. A concatenação é feita pela função CONCAT no segundo exemplo e depois somente precisamos imprimir uma variável, ao invés de duas, evitando assim problemas de interpretação. Datas? Não se perca Muitas vezes o trabalho com datas é um pesadelo para o programador. Soma de dias, meses, em que dia da semana caiu tal data e assim por diante.
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
13
Manuais e recursos para desenvolvimento web www.criarweb.com
Como para strings, bancos de dados também possuem um conjunto interessante de funções para a manipulação de datas. Vamos ver algumas. A data atual Já vi muito programador criar função para a inserção de datas dentro de registros em bases de dados. Acredito que isso seja por não conhecer uma pequena mas muito útil função chamada now(). Com ela, a data e/ou hora atual são armazenadas em campos que necessitam este valor. mysql_query("INSERT INTO tabela (data) VALUES (now())",$conexao);
Esta função simplesmente pega a informação de data e hora do servidor e insere no campo que deseja (neste exemplo, em data). Mas cuidado; se o servidor está com a data/hora erradas, o valor que será inserido também estará errado. Assim é interessante manter o servidor com horário sempre sincronizado com time servers existentes na Internet. Além disso, em alguns momentos precisamos saber em que semana estamos do ano ou ainda quantas semanas faltam para o fim do ano. Ao invés de complexos códigos de linguagem, podemos usar a base de dados para nos informar este resultado rapidamente. Por exemplo, em que semana do mês estamos agora? print mysql_result(mysql_query("SELECT WEEK(now())",$conexao),0); // resultado: 18
Aqui foi usada a função WEEK que retorna o número da semana de uma determinada data. Neste caso, a data informada é “hoje” pois usamos como parâmetro de data a função now() que, como já apresentado anteriormente, é a data atual do servidor. Outra tarefa comum com datas é a soma de dias em uma data específica. Pode parecer simples mas como o formato de data é diferente de formatos numéricos e strings, muitas vezes o resultado está errado e não sabemos porquê. A forma mais simples é novamente deixar o banco de dados trabalhar por você. Então para acrescentar, por exemplo, dez dias à data atual, fazemos: print mysql_result(mysql_query("SELECT DATE_ADD(now(),INTERVAL 10 DAY)", $conexao),0); // resultado: 2006-05-16
Com isso temos, em uma única linha, o valor que precisamos com a certeza que se trata de uma data válida, inclusive contando meses que possuem somente 28,29 ou 30 dias (experimente fazer a soma de 10 dias à data de 25/02/2006 e verá o resultado). Conclusão
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
14
Manuais e recursos para desenvolvimento web www.criarweb.com
Pequenas e simples funções quando bem utilizadas facilitam a vida de qualquer desenvolvedor. Assim, antes de “quebrar a cabeça” com dezenas de linhas de código para resolver um problema ou demanda, procure saber se as ferramentas que está utilizando não dispõem de formas mais simples para a solução deste problema. Muitas vezes a solução mais simples está diante dos olhos e perdemos tempo tentando algo diferente. Estes exemplos são pequenos e simples se comparados a enorme gama de opções existentes nas bases de dados. Funções para data, strings, funções matemáticas e outras tantas estão disponíveis na maioria das bases de dados relacionais existentes hoje em dia. Para o MySQL, acesse http://dev.mysql.com/doc/refman/4.1/pt/functions.html. Já para o PostgreSQL, acesse http://www.postgresql.org/docs/8.1/static/functions.html Espero que tenha gostado e aprendido um pouco mais. Abraços! Obs: Os códigos deste artigo podem ser encontrados em http://www.michelazzo.com.br na seção de downloads. Copyright 2006 Paulino Michelazzo - http://www.michelazzo.com.br Obra licenciada sob Creative Commons Developing Nations 2.0 Artigo por Paulino Michelazzo
Tabelas temporárias no Sql Server A sintaxe para criar uma tabela temporária no Sql Server é bastante simples, basta acrescentar o # antes do nome da mesma. Sintaxe: CREATE TABLE #nomeTable ( nomecampoA varchar(80), nomecampoB money ) Tabelas temporárias são muito utilizadas quando precisamos reunir vários registros de várias tabelas em uma única seleção e exibi-las em uma aplicação qualquer (p.ex.: Delphi, Visual Studio, ASP.NET, etc.). . É fundamental para aplicações cliente/servidor onde vários usuários estão acessando aquela procedure ao mesmo tempo. Aqui vai um exemplo prático da utilização de tabelas temporárias.É importante saber que a tabela temporária só existe enquanto a procedure está sendo executada, após a execução da mesma ela é automaticamente excluída. Aproveitei para colocar um exemplo utilizando o CASE do Sql Server CREATE PROCEDURE TesteTabelaTemporaria Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
15
Manuais e recursos para desenvolvimento web www.criarweb.com
as create table #tmpTotalPage (mes smallint null, totalmes smallint null, mediames decimal(9, 3) null ) Insert into #tmpTotalPage ( mes, totalmes, media) (select DATEPART(MONTH,data) as Mes, count(*) as TotalAcessos, null from Acessos AS AC INNER JOIN CadastroTB AS C ON AC.idcad = C.idCad group by DATEPART(MONTH,data)) select mes, totalmes, media = case when mes = 1 then totalmes / 31 when mes = 2 then totalmes / 28 when mes = 3 then totalmes / 30 when mes = 4 then totalmes / 31 when mes = 5 then totalmes / 30 when mes = 6 then totalmes / 31 when mes = 7 then totalmes / 30 when mes = 8 then totalmes / 31 when mes = 9 then totalmes / 30 when mes = 10 then totalmes / 31 when mes = 11 then totalmes / 30 when mes = 12 then totalmes / 31 end from #tmpTotalPage Por enquanto é só, até a próxima pessoal! Artigo por Fabio Correa
Adquirindo informações do Usuário com a classe System Acredito que muitas pessoas já tiveram a necessidade de saber qual o nome do sistema operacional de um usuário, o seu login do Windows, o diretório home etc. em suas aplicações. Se você é um dos que se enquadram nessa situação, saiba que existe uma forma de adquirir essas informações: através da função System.getProperty(). Segue um exemplo: public class Main{ public static void main( String[] args ) { System.out.println("Usuario: " + System.getProperty("user.name").toUpperCase()); System.out.println("Sistema Operacional: " + System.getProperty("os.name").toUpperCase()); } }
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
16
Manuais e recursos para desenvolvimento web www.criarweb.com
Veja a saída: Usuário: GLAUCIO Sistema Operacional: WINDOWS XP
Abaixo seguem alguns parâmetros para a função getProperty(): os.arch – Retorna a arquitetura do Sistema operacional os.version – Retorna a versão do Sistema operacional os.name – Nome do Sistema Operacional java.version – Retorna a versão da JRE java.home – Diretório de Instalação Java java.class.path java.class.path – Retorna o Class Path user.home user.home – Diretório home do usuário user.name – Nome da conta do usuário A lista completa encontra-se neste endereço: http://java.sun.com/j2se/1.4.2/docs/a http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ pi/java/lang/System.html#getProperties() System.html#getProperties() Essa recurso também pode ser usado em JSPs: Código da JSP:
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
17
Manuais e recursos para desenvolvimento web www.criarweb.com
Saída:
Esse tipo de função permite que, por exemplo, quando um usuário acessar o sistema, seu login seja obrigatoriamente o mesmo do Sistema Operacional. Isso oferece ao administrador do sistema total controle de quem está usando a ferramenta, garantindo que o usuário possui uma conta na Intranet. Artigo por Glaucio por Glaucio Guerra
Alguns truques práticos Eliminar chamadas aos bancos de dados Em páginas do tipo portal por tal nas que nas laterais se encontram links que são impressos a partir de bancos de dados (distintas seções, serviços,...) existe existe sempre um efeito lentalizador devido a que se trata de páginas altamente visitadas que efetuam múltiplas chamadas a BD sistematicamente em cada uma de suas páginas. Uma forma de agilizar a visualização destas páginas é textualizando estes links a partir de scripts internos. Colocamos o exemplo de Criarweb: Como se pode ver, ver, na lateral existem seções como "Suas Páginas", "Manuais" cujos links estão armazenados no banco de dados. Entretanto, os links que se visualizam na página não foram obtidos por chamadas a banco de dados e sim que, cada vez que um novo elemento da seção é adicionado, isto se atualiza automaticamente, por meio de um script, um arquivo texto no qual o novo link é incluído e o mais antigo é eliminado. De fato, este arquivo de texto é o que é inserido no código fonte da página. Deste modo, evitamos meia dúzia de chamadas a bancos Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
18
Manuais e recursos para desenvolvimento web www.criarweb.com
de dados cada vez que uma página é vista, o qual permite otimizar recursos de servidor de uma maneira significativa. Eliminar palavras curtas e repetições Em situações na qual nosso banco de dados tem que armazenar campos de texto extremamente longos, e tais campos são requeridos para realizar seleções do tipo LIKE '%algo %', os recursos do BD podem se ver sensivelmente minguados Uma forma de ajudar a gerenciar este tipo de buscas é incluindo um campo adicional. Este campo adicional pode ser criado automaticamente por meio de scripts e nele incluiríamos o texto original, do qual teremos eliminado palavras triviais como artigos, preposições ou possessivos. Além disso, nos encarregaremos de eliminar as palavras que estiverem repetidas. Desta forma poderemos diminuir sensivelmente o tamanho do campo que vai ser realmente consultado. Comentamos em outros capítulos que os campos de texto de mais de 255 25 5 caracteres denominados memo não podem ser indexados. Se ainda depois desta primeira filtragem nosso campo continuar sendo longo demais para ser indexado, o que se pode fazer é corta-lo em pedaços de 255 caracteres de maneira que o armazenemos em diferentes campos que poderão poder ão ser indexados e portanto, consultados com maior rapidez. Artigo por Rubén por Rubén Alvarez
Criação de tabelas Em geral, a maioria dos bancos de dados possui potentes editores de bancos que permitem a criação rápida e simples de qualquer tipo de tabela com qualquer tipo de formato. Entretanto, uma vez que o banco de dados esteja hospedado no servidor, servidor, pode acontecer o caso de que queiramos introduzir uma nova tabela já seja com caráter temporário (para gerenciar um carrinho de compra, por exemplo) ou permanente, por necessidades ne cessidades concretas de nossa aplicação. Nestes casos, podemos, a partir de uma sentença SQL, criar a tabela com o formato que desejarmos, o qual pode nos poupar mais que um quebra-cabeça. q uebra-cabeça. Estes tipos de sentenças são especialmente úteis para bancos de dados como Mysql, os quais trabalham diretamente com comandos SQL e não por meio de editores. Para criar uma tabela devemos especificar e specificar diversos dados: O nome que queremos atribuir, atribuir, os nomes dos campos e suas características. Ademais, pode ser necessário especificar quais destes campos vão ser índices e de que tipo serão. A sintaxe de criação pode variar ligeiramente de um banco de dados para outro já que os tipos de campos aceitos, não estarão completamente padronizados. A seguir explicamos meramente a sintaxe desta sentença e lhes propomos uma série de Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
19
Manuais e recursos para desenvolvimento web www.criarweb.com
exemplos: Sintaxe Create Table nome_tabela ( nome_campo_1 tipo_1 nome_campo_2 tipo_2 nome_campo_n tipo_n Key(campo_x,...) ) Ponhamos agora como exemplo a criação da tabela pedidos que empregamos em capítulos anteriores: Create Table pedidos ( id_pedido INT(4) NOT NULL AUTO_INCREMENT, id_cliente INT(4) NOT NULL, id_artigo INT(4)NOT NULL, data DATE, quantidade INT(4), total INT(4), KEY(id_pedido,id_cliente,id_artigo) ) Neste caso criamos os campos id os quais são considerados de tipo inteiro de uma longitude especificada pelo número entre parênteses. Para id_pedido requeremos que tal campo se incremente automaticamente (AUTO_INCREMENT) de uma unidade a cada introdução a um novo registro para, desta forma, automatizar sua criação. Por outro lado, para evitar uma mensagem de erro, é necessário requerer que os campos que vão ser definidos como índices não possam ser nulos (NOT NULL). O campo data é armazenado com formato de data (DATE) para permitir sua correta exploração a partir das funções previstas a tal efeito. Finalmente, definimos os índices numerando-os entre parênteses precedidos da palavra KEY ou INDEX. Da mesma forma poderíamos criar a tabela de artigos com uma sentença como esta: Create Table artigos ( id_artigo INT(4) NOT NULL AUTO_INCREMENT, titulo VARCHAR(50), autor VARCHAR(25), editorial VARCHAR(25), preco REAL, KEY(id_artigo) ) Neste caso pode-se ver que os campos alfanuméricos são introduzidos da mesma forma que os numéricos. Voltemos a recordar que em tabelas que têm campos comuns é de vital Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
20
Manuais e recursos para desenvolvimento web www.criarweb.com
importância definir estes campos da mesma forma para o bom funcionamento da base. Muitas são as opções que se oferecem ao gerar tabelas. Não vamos a trata-las detalhadamente, pois sai do estritamente prático. Mostraremos somente alguns dos tipos de campos que podem ser empregados na criação de tabelas com suas características: Tipo
Bytes
INT ou INTEGER
4
Números inteiros. Existem outros tipos de maior ou menor longitude específicos de cada banco de dados.
DOUBLE ou REAL
8
Números reais (grandes e com decimais). Permitem armazenar todo tipo de número não inteiro.
CHAR
Descrição
1/caractere Alfanuméricos de longitude fixa pré-definida
VARCHAR 1/caractere+ Alfanuméricos de longitude variável 1 DATE
BLOB BIT ou BOOLEAN
3
Datas, existem múltiplos formatos específicos de cada banco de dados
1/caractere+ Grandes textos não indexáveis 2 1
Armazenam um bit de informação (verdadeiro ou falso)
Artigo por Rubén Alvarez
SQL e Programação de Banco de Dados Quero me apresentar a você e iniciar um contato periódico para tratarmos assuntos relacionados à linguagem SQL e à programação de banco de dados. Trabalho com banco de dados há algum tempo e sei o quanto é importante trocar experiências com outros profissionais. Ninguém é capaz de extrair o máximo de um banco de dados, mas, juntos, podemos realizar mais e de uma maneira cada vez melhor. Minha experiência maior tem sido desenvolvida junto ao banco de dados Oracle, mas a padronização do comando SQL e pelo fato de os conceitos de programação de um banco de dados serem facilmente aplicados a qualquer outro banco de dados, faz com que possamos tratar destes assuntos quase que universalmente.
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
21
Manuais e recursos para desenvolvimento web www.criarweb.com
SQL A linguagem SQL (Structured Query Language) é a base para utilização de bancos de dados relacionais. Com a utilização dos comandos básicos (INSERT, DELETE, UPDATE e SELECT) pode-se resolver a maior parte dos problemas relacionados a manutenção e extração de dados no banco de dados. Com o SQL é possível criar as estruturas básicas de armazenamento, como tabelas e índices. Também há comandos específicos da linguagem para o controle e segurança relacionado a um banco de dados. Em princípio, os comandos SQL são divididos em: • • • •
DDL (Data Definition Language) ou Linguagem de definição de dados DML (Data Manipulation Language) ou Linguagem de manipulação de dados DQL (Data Query Language) ou Linguagem de recuperação de dados DCL (Data Control Language) ou Linguagem de controle de dados O SQL tem sido aprimorado ao longo do tempo. Duas entidades (ANSI – American National Standards Institute e ISO – International Standards Organization) vêm, desde 1986, publicando padrões de especificação da linguagem SQL. Vamos discutir como abordar e tirar o máximo de proveito desta linguagem que é extremamente importante para todos os profissionais de banco de dados. Os principais tópicos que serão de interesse envolvem:
• • • • •
Fundamentos da linguagem SQL Extensões e particularidades de cada banco de dados Melhoria no desempenho de consultas Utilização de funções analíticas em banco de dados Tendências do uso da linguagem Naturalmente a idéia é ter uma visão prática, com exemplos e com a abertura de uma discussão entre todos os leitores. Programação de Banco de Dados Os comandos da linguagem SQL são muito poderosos, mas normalmente consegue-se melhorar o desempenho das aplicações através da programação do banco de dados. Ao desenvolver módulos que sejam executados diretamente no servidor diminui-se o tráfego de informações na rede, esconde-se boa parte das estruturas das tabelas e agiliza-se o processamento e retorno das mensagens. Internamento o banco de dados possui mecanismos integrados que permitem unir as estruturas tradicionais de programação com os comandos SQL. O banco de dados possui mecanismos próprios que podem ser utilizados em favor do desenvolvedor. Cada banco de dados possui um conjunto específico de comandos que definem a linguagem de programação do banco de dados. No caso do Oracle, a linguagem é o PL/SQL, o SQL Server possui o Transact-SQL, o DB2 possui sua própria linguagem de programação, o PostGreSQL possui diversas extensões que podem ser utilizadas como linguagem de programação e o MySQL lançou sua mais recente versão com a possibilidade de programar o servidor. Cada banco de dados é único sob este aspecto, mas todos trabalham sobre os mesmos conceitos. É possível criar módulos programáveis, como funções, procedimentos, objetos, pacotes, gatilhos, etc. Em todos os casos, há um engine responsável pela integração e execução dos módulos no servidor de banco de dados.
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
22
Manuais e recursos para desenvolvimento web www.criarweb.com
Desta forma, os tópicos que serão trabalhados serão: • • • • •
Fundamentos de programação de banco de dados Aspectos avançados da programação Desempenho dos módulos Programação aliada à extração de dados gerenciais Tendências em programação de banco de dados Como se pode notar, os tópicos são quase os mesmos da linguagem SQL. Também teremos artigos que poderão ser implementados, testados e melhorados por todos os leitores.
Artigo por Eber M. Duarte
Funções para buscas com datas em Access Buscas com datas em Access Recebemos uma pergunta recentemente de um amigo que desejava realizar buscas em Access utilizando, nas condições do Where, campos do tipo data. Depois de várias tentativas resgatamos umas anotações que podem ser interessantes para publicar. Seguro que servem de ajuda a outras pessoas que tenham que trabalhar com datas em consultas de Access. A consulta era a seguinte: Tenho uma tabela com vários campos. Dois deles são datas, que correspondem com um intervalo. Um deles é a data de início do intervalo (datadesde) e outro a de final do intervalo (dataate) Queria saber como se pode fazer uma consulta SQL em Access para obter os registros cujo intervalo de datas contenha o dia de hoje. Ou seja, que a data desde seja menor que hoje e data até seja maior que hoje.
Estivemos primeiro fazendo duas provas sem êxito, comparando as datas com operadores aritméticos. Em alguns casos obtivemos a resposta esperada, porém nem sempre funcionavam as sentenças e tínhamos problemas ao executa-las desde Access ou desde o servidor web, porque não devolviam os mesmos resultados. Função DateDiff() Afinal, a resposta que propusemos passou por utilizar a função DateDiff, que serve para obter a diferença entre duas datas. Por exemplo: DateDiff("y", #06/10/2004#, Now()) Conta-nos os dias que passaram desde seis de outubro de 2004. Nós podemos utiliza-la como condição em um where de uma sentença SQL. Por exemplo, para uma sentença como esta: DateDiff("y",A,B)
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
23
Manuais e recursos para desenvolvimento web www.criarweb.com
Se são iguais, a função devolverá zero. Se A é uma data anterior a B, então a função devolverá um número de dias que será maior que zero. Se A é uma data posterior a B, então devolverá um número de dias que será menor que zero. Temos que comparar o dia de hoje com as datas desde e ate. Hoje tem que ser maior que desde e menor que ate. Fica como resultado esta sentença: • •
•
SELECT * FROM vuelos WHERE DateDiff('y',datadesde,now())>=0 and DateDiff('y',dataate,nom())<=0 Nota: Há que ter cuidado com o idioma das datas, pois em português se escrevem de maneira diferente que em inglês. Access tenta interpretar a data corretamente, por exemplo, se introduzimos 02/26/04 pensará que está trabalhando em datas em inglês e se introduzimos 26/02/04 pensará que estamos escrevendo as datas em português. O problema é com uma data como 02/02/04 que seu valor dependerá de como esteja configurado o Access, em português ou em inglês.
Função DatePart Serve para extrair parte de uma data. Recebe dois parâmetros, o primeiro indica mediante um string a parte a obter. O outro parâmetro é a data com a que se deseja trabalhar. DatePart("m",data) Neste caso está sendo indicado que se deseja obter o mês do ano. Outro valor possível para o primeiro parágrafo é, por exemplo "yyyy", que se utiliza para obter o ano com quatro dígitos. Um exemplo de sentença SQL que utiliza esta função pode ser a seguinte: SELECT DatePart("yyyy",validadedesde) FROM voos
Função DateAdd Esta última função que vamos ver no presente artigo serve para acrescentar à data, algo como dias, meses ou anos. Para isso a função recebe três parâmetros, o primeiro corresponde com um string para indicar as unidades do que desejamos acrescentar, por exemplo, dias, meses ou anos. O segundo parâmetro é o número de dias, meses ou anos a adicionar e o terceiro parâmetro é a data a qual somar esses valores. Vemos um exemplo de sua sintaxe: DateAdd("yyyy",10,validadedesde) Neste exemplo a função DateAdd devolveria uma data dez anos posterior a validadedesde. Outros valores para o string do primeiro parâmetro são "d", para acrescentar dias, ou "m", para acrescentar meses. Um exemplo do funcionamento desta função em uma sentença SQL é a seguinte: SELECT DateAdd("yyyy",10,validadedesde) FROM voos
Artigo por Miguel Angel Alvarez - Tradução de JML
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
24
Manuais e recursos para desenvolvimento web www.criarweb.com
Função em SQL para o cálculo de dias de trabalho /*Primeiramente declaramos que vamos criar uma função, neste caso se chama Dif Dias e recebe dois parâmetros, a data inicial do período e a final*/ CREATE FUNCTION DifDias(@StartDate DATETIME,@EndDate DATETIME) RETURNS integer AS Begin //Com esta variavel calculamos quantos dias "normais" existem na classe de datas DECLARE @DaysBetween INT //Com esta variavel acumulamos os dias totais DECLARE @BusinessDays INT //esta variavel nos serve de contador para saber quando chegarmos ao ultimo dia da classe DECLARE @Cnt INT /*esta variavel eh a que comparamos para saber se o dia que esta calculando eh sabado ou domingo*/ DECLARE @EvalDate DATETIME /*Estas duas variaveis servem para comparar as duas datas, se sao iguais, a funcao nos regressa um 0*/ DECLARE @ini VARCHAR(10) DECLARE @fin VARCHAR(10) //Iniciamos algumas variaveis SELECT @DaysBetween = 0 SELECT @BusinessDays = 0 SELECT @Cnt=0 //Calculamos quantos dias normais existem na classe de datas SELECT @DaysBetween = DATEDIFF(DAY,@StartDate,@EndDate) + 1 /*Ordenamos o formato das datas para que não importando como se proporcionem se comparem igual*/ SELECT @ini = (SELECT CAST((CAST(datepart(dd,@StartDate)AS VARCHAR(2))+'/'+ CAST(datepart(mm,@StartDate)AS VARCHAR(2))+'/'+CAST(datepart(yy,@StartDate)AS VARCHAR(4))) as varchar(10))) SELECT @fin = (SELECT CAST((CAST(datepart(dd,@EndDate)AS VARCHAR(2))+'/'+ CAST(datepart(mm,@EndDate)AS VARCHAR(2))+'/'+ CAST(datepart(yy,@EndDate)AS VARCHAR(4)))as varchar(10))) //Comparam-se as duas datas IF @ini <>@fin BEGIN /*Se a diferenca de datas for igual a dois, eh porque so foi transcorrido um dia, portanto somente se valida de que nao vai marcar dias de mais*/ IF @DaysBetween = 2 BEGIN SELECT @BusinessDays = 1 END ELSE BEGIN Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
25
Manuais e recursos para desenvolvimento web www.criarweb.com WHILE @Cnt < @DaysBetween BEGIN /*Iguala-se a data que vamos calcular para saber se eh sabado ou domingo na variavel @EvalDate somando os dias que marque o contador, o qual nao deve ser maior que o numero total de dias que existem na classe de datas*/ SELECT @EvalDate = @StartDate + @Cnt /*Utilizando a funcao datepart com o parametro dw que calcula que dia da semana corresponde uma data determinada, determinados que nao seja sabado (7) ou domingo (1)*/ IF ((datepart(dw,@EvalDate) <> 1) and (datepart(dw,@EvalDate) <> 7) ) BEGIN /*Se nao eh sabado ou domingo, entao se soma um ao total de dias que queremos desdobrar*/ SELECT @BusinessDays = @BusinessDays + 1 END //Soma-se um dia a mais ao contador SELECT @Cnt = @Cnt + 1 END END END ELSE BEGIN //Se fosse certo que as datas eram iguales se desdobraria em zero SELECT @BusinessDays = 0 END //Ao finalizar o ciclo, a funcao regressa o numero total de dias return (@BusinessDays) END
Artigo por Rosendo Lopez Robles
SQL com Oracle Introdução: Antes de começar, gostaria de dizer que este curso está baseado em Oracle, ou seja, os exemplos expostos e o material foram atualizados sobre Oracle. Por outro lado dizer que acho interessante saber algo de SQL antes de começar com MYSQL, já que, embora existam algumas mudanças insignificantes, sabendo manejar SQL você saberá manejar MYSQL. Algumas características: SQL: Structured query language. • • •
Permite a comunicação com o sistema administrador de banco de dados. Em seu uso pode-se especificar o que quer o usuário. Permite fazer consulta de dados.
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
26
Manuais e recursos para desenvolvimento web www.criarweb.com
Tipos de dados: CHAR: Têm uma longitude fixa. Armazena de 1 a 255. Se introduzimos uma cadeia de menos longitude que a definida se preencherá com brancos à direita até ficar completa. Se introduzirmos uma cadeia de maior longitude que a fixada nos dará um erro.
• • •
•
VARCHAR: Armazena cadeias de longitude variável. A longitude máxima é de 2000 caracteres. Se introduzimos uma cadeia de menor longitude que a que está definida, se armazena com essa longitude e não se preencherá com brancos nem com nenhum outro caractere à direita até completar a longitude definida. Se introduzimos uma cadeia de maior longitude que a fixada, nos dará um erro.
• • •
•
NUMBER: Armazenam-se tanto inteiros como decimais. Number (precisão, escala) Exemplo:
• • •
X=number (7,2) X=155'862 à Erro já que só pode tomar 2 decimais X= 155'86 à Bem Nota: A categoria máxima vai de 1 a 38.
LONG: •
Não armazena números de tamanho grande, e sim cadeias de caracteres de até 2 GB
DATE: •
Armazena a data. Armazena da seguinte forma:
Seculo/Ano/Mes/Dia/Hora/Minutos/Segundos
RAW: •
Armazena cadeias de Bytes (gráficos, áudio…)
LONGRAW: •
Como o anterior, mas com maior capacidade.
ROWID: •
•
Posição interna de cada uma das colunas das tabelas. Sentenças de consultas de dados
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
27
Manuais e recursos para desenvolvimento web www.criarweb.com
Select: Select [ALL | Distinct] [expresao_coluna1, expresao_coluna2, …., | *] From [nome1, nome_tabela1, …, nome_tabelan] {[Where condicao] [Order By expresao_coluna [Desc | Asc]…]};
Vamos explicar como ler a consulta anterior e assim seguir a pauta para todas as demais. Quando compomos [] significa que a que vai dentro deve existir, e sim, além disso, colocamos | significa que deveremos escolher um valor dos que colocamos e não mais de um. Em troca se colocarmos {} significa que o que vai dentro das chaves pode ir ou não, ou seja, é opcional e se colocará segundo a consulta. Nota: No select o valor por default entre ALL e DISTINCT é ALL. • •
• • • •
•
Alias = O novo nome que se dá a uma tabela. Coloca-se entre aspas Order By = Ordena ascendentemente (Asc) (valor por default) ou descendentemente (Desc). All = Recupera todas as filas da tabela embora estejam repetidas. Distinct = Só recupera as filas que são distintas. Desc Emple; = Dá um resumo da tabela e suas colunas. Neste caso da tabela Emple. Not Null= Se aparecer em uma lista de uma coluna significa que a coluna não pode ter valores nulos. Null= Se estiver nulo. Nota: Note que cada consulta de SQL que fazemos temos de termina-la com um ponto e vírgula";".
Vários exemplos para vê-lo mais claro: SELECT JOGADOR_NO, SOBRENOME, POSICAO, TIME FROM JOGADORES WHERE TIME_NO = 'FLAMENGO' ORDER BY SOBRENOME;
Este exemplo mostra o número do jogador (jogador_no) o sobrenome (Sobrenome), a posição na que joga (Posição), e o time (Time) ao que pertence. Selecionará todos os dados da tabela jogadores onde (Where) o nome do time (Time_No) for igual que a palavra 'Flamengo' e se ordenará (order by) sobrenome. Observe também que não põe nem 'Distinct' nem 'All'. Por padrão, gerará a sentença com ALL. SELECT * FROM JOGADORES WHERE POSICAO = 'ATACANTE' ORDER BY JOGADOR_NO;
Este exemplo mostra todos os campos da tabela jogadores onde (Where) a posição for igual que 'Atacante' e o ordena por número de jogador. Ao não colocar nada se supõe que é ascendentemente (Asc). SELECT * FROM JOGADORES WHERE TIME_NAO = 'FLAMENGO' AND POSICAO = 'ATACANTE' ORDER BY SOBRENOME DESC, JOGADOR_NAO ASC;
Neste exemplo seleciona todos os campos da tabela jogadores onde (Where) o nome do time Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
28
Manuais e recursos para desenvolvimento web www.criarweb.com
for igual a 'Flamengo' e a posição dos jogadores for igual a 'Atacante'. Por ultimo os ordena por 'Sobrenome' descendentemente e por número de jogador ascendentemente. Artigo por Agustin Jareño
SQL com Oracle. Operadores Operadores aritméticos: + = Soma - = Subtração * = Multiplicação / = Divisião Operadores de comparação e lógicos: !> = Diferente >= = Maior ou igual que <= = Menor ou igual que = = Igual que Like = Utiliza para unir cadeias de caracteres. Propriedades: % = representa qualquer cadeia de caracteres de 0 ou mais caracteres. _= representa um único caractere qualquer. Not = Negação And = e a and b Certo se são certas a e b. Or = o a or b Certo se a ou b são certas Vejamos dois exemplos: Obtemos os dados dos jogadores cujos sobrenomes comecem com a letra "S": SELECT SOBRENOMES FROM JOGADORES WHERE SOBRENOMES LIKE 'S%'; Obtemos aqueles sobrenomes que tiverem uma "R" na segunda posição: SELECT SOBRENOMES FROM JOGADORES WHERE SOBRENOMES LIKE '_R*';
Obtemos aqueles sobrenomes que começam por "A" e tem uma "o" em seu interior: SELECT SOBRENOMES FROM JOGADORES WHERE SOBRENOMES LIKE 'A%O%';
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
29
Manuais e recursos para desenvolvimento web www.criarweb.com
Comprovação com conjuntos de valores: • •
In= permite saber se uma expressão pertence ou não a um conjunto de valores. Between= permite saber se uma expressão está ou não entre esses valores:
Exemplo: SELECT SOBRENOMES FROM JOGADORES WHERE JOGADOR_NUM IN (10, 20);
Seleciona os sobrenomes dos jogadores onde o número de jogador (Jogador_num) seja (In) ou 10 ou 20 SELECT SOBRENOMES FROM JOGADORES WHERE SALARIO NOT BETWEEN 15000000 AND 20000000;
Seleciona os sobrenomes dos jogadores onde o salário destes não esteja entre (Not Between) 15000000 e 20000000. Artigo por Agustin Jareño
Sub-consultas SQL Sub-consultas: Consulta que se faz sobre os dados que nos dá outra consulta. Seu formato é: SELECT______ FROM________ WHERE CONDICAO OPERADOR (SELECT ______ FROM ___________ WHERE CONDICAO OPERADOR); Exemplo:
Obtemos os jogadores com a mesma posição que "Sanchez": SELECT SOBRENOME FORM EMPLE WHERE POSICAO = (SELECT OFICIO FROM EMPLE WHERE SOBRENOME LIKE 'GIL');
Selecionamos em todos os campos da tabela Jogadores cuja sede está em Madrid ou Barcelona: SELECT * FROM JOGADORES WHERE EQUIPE_NOM IN (SELECT EQUIPE_NOM FROM SEDE WHERE LOC IN ('MADRID', 'BARCELONA'); FROM SEDE WHERE LOC IN ('MADRID', 'BARCELONA');
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
30
Manuais e recursos para desenvolvimento web www.criarweb.com
Artigo por Agustin Jareño
Funções SQL Funções de valores simples: ABS(n)= Devolve o valor absoluto de (n). CEIL(n)= Obtém o valor inteiro imediatamente superior ou igual a "n". FLOOT(n) = Devolve o valor inteiro imediatamente inferior ou igual a "n". MOD (m, n)= Devolve o resto resultante de dividir "m" entre "n". NVL (valor, expressão)= Substitui um valor nulo por outro valor. POWER (m, exponente)= Calcula a potência de um número. ROUND (numero [, m])= Arredonda números com o número de dígitos de precisão indicados. SIGN (valor)= Indica o signo do "valor". SQRT(n)= Devolve a raiz quadrada de "n". TRUNC (numero, [m])= Trunca números para que tenham uma certa quantidade de dígitos de
precisão.
VAIRANCE (valor)=
Devolve a média de um conjunto de valores.
Funções de grupos de valores: AVG(n)= Calcula o valor médio de "n" ignorando os valores nulos. COUNT (* | Expressão)= Conta o número de vezes que a expressão avalia
não nulo. A opção "*" conta todas as filas selecionadas. MAX (expressão)= Calcula o máximo. MIN (expressão)= Calcula o mínimo. SUM (expressão)= Obtém a soma dos valores da expressão. GREATEST (valor1, valor2…)= Obtém o maior valor da lista. LEAST (valor1, valor2…)= Obtém o menor valor da lista.
algum dado com valor
Funções que devolvem valores de caracteres: CHR(n) = Devolve o caractere cujo valor em binário é equivalente a "n". CONCAT (cad1, cad2)= Devolve "cad1" concatenada com "cad2". LOWER (cad)= Devolve a cadeia "cad" em minúsculas. UPPER (cad)= Devolve a cadeia "cad" em maiúsculas. INITCAP (cad)= Converte a cadeia "cad" a tipo título. LPAD (cad1, n[,cad2])= Adiciona caracteres à esquerda da cadeia até que tenha
longitude.
uma certa
RPAD (cad1, n[,cad2])= Adiciona caracteres à direita até que tenha uma certa longitude. LTRIM (cad [,set])= Suprime um conjunto de caracteres à esquerda da cadeia. RTRIM (cad [,set])= Suprime um conjunto de caracteres à direita da cadeia. REPLACE (cad, cadeia_busca [, cadeia_substitucao])= Substitui um caractere ou caracteres de uma
cadeia com 0 ou mais caracteres. SUBSTR (cad, m [,n])= Obtém parte de uma cadeia. TRANSLATE (cad1, cad2, cad3)= Converte caracteres de uma cadeia em caracteres diferentes, segundo um plano de substituição marcado pelo usuário.
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
31
Manuais e recursos para desenvolvimento web www.criarweb.com
Funções que devolvem valores numéricos: ASCII(cad)= Devolve o valor ASCII da primeira letra da cadeia "cad". INSTR (cad1, cad2 [, comeco [,m]])= Permite uma busca de um conjunto de
cadeia, mas não suprime nenhum caractere depois. LENGTH (cad)= Devolve o número de caracteres de cad.
caracteres em uma
Funções para o manejo de datas: SYSDATE= Devolve a data do sistema. ADD_MONTHS (data, n)= Devolve a data "data" incrementada em "n" meses. LASTDAY (data)= Devolve a data do último dia do mês que contém "data". MONTHS_BETWEEN (data1, data2)= Devolve a diferença em meses entre as datas "data1" e "data2". NEXT_DAY (data, cad)= Devolve a data do primeiro dia da semana indicado por "cad" depois da
data indicada por "data".
Funções de conversão: TO_CHAR= Transforma um tipo DATE ou NUMBER em uma cadeia TO_DATE= Transforma um tipo NUMBER ou CHAR em DATE. TO_NUMBER= Transforma uma cadeia de caracteres em NUMBER.
de caracteres.
Artigo por Agustin Jareño
Agrupamento e combinação de elementos com SQL Agrupamento de elementos. Group by e Having: Para saber qual é o salário médio de cada departamento da tabela Jogadores seria: SELECT TIME_NO, AVG (SALARIO) "SALARIO MEDIO" FROM JOGADORES GROUP BY DEPT_NO;
A sentença "Select" possibilita agrupar um ou mais conjuntos de filas. O agrupamento se realiza mediante a cláusula "GROUP BY" pelas comunas especificadas e na ordem especificada. Formato: SELECT… FROM… GROUP BY COLUNA1, COLUNA2, COLUNAN… HAVING CONDICAO GROUP BY …
Os dados selecionados na sentença "Select" que leva o "Group By" devem ser: •
•
•
Uma constante. Uma função de grupo (SUM, COUNT, AVG…) Uma coluna expressa no Group By.
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
32
Manuais e recursos para desenvolvimento web www.criarweb.com
A cláusula Group By serve para calcular propriedades de um ou mais conjuntos de filas. Se se seleciona mais de um conjunto de filas, Group By controla que as filas da tabela original sejam agrupadas em um temporário. A cláusula Having se emprega para controlar qual dos conjuntos de filas se visualiza. Avalia-se sobre a tabela que devolve o Group By. Não pode existir sem Group By. Having é parecido ao Where, porém trabalha com grupos de filas; pergunta por uma característica de grupo, ou seja, pergunta pelos resultados das funções de grupo, o qual Where não pode fazer. Combinação externa (outer joins): Permite-nos selecionar algumas filas de uma tabela embora estas não tenham correspondência com as filas da outra tabela com a que se combina. Formato: SELECT TABELA1.COLUNA1, TABELA1.COLUNA2, TABELA2.COLUNA1, TABELA2.COLUNA2 FROM TABELA1, TABELA2 WHERE TABELA1.COLUNA1 = TABELA2.COLUNA1 (+);
Isto seleciona todas as filas da tabela "tabela1" embora não tenham correspondência com as filas da tabela "tabela2", se utiliza o símbolo +. O resto de colunas da tabela "tabela2" se preenche com NULL. Union, intersec e minus: Permite combinar os resultados de vários "Select" para obter um único resultado. Formato: SELECT… FROM… WHERE… OPERADOR_DE_CONJUNTO SELECT…FROM…WHERE…
Combina os resultados de duas consultas. As filas duplicadas que aparecem se reduzem a uma fila única. UNION ALL= Como a anterior, porém aparecerão nomes duplicados. INTERSEC= Devolve as filas que são iguais em ambas consultas. Todas as filas duplicadas serão eliminadas. MINUS= Devolve aquelas filas que estão na primeira "Select" e não estão na segunda "Select". As filas duplicadas do primeiro conjunto se reduzirão a uma fila única antes que comece a comparação com o outro conjunto. UNION=
Regras para a utilização de operadores de conjunto: • •
• •
As colunas das duas consultas se relacionam em ordem, da esquerda à direita. Os nomes de coluna da primeira sentença "Select" não tem porque ser os mesmos que os nomes da segunda. Os "Select" necessitam ter o mesmo número de colunas. Os tipos de dados devem coincidir, embora a longitude não tem que ser a mesma.
> Artigo por Agustin Jareño
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
33
Manuais e recursos para desenvolvimento web www.criarweb.com
Manipulação de dados com SQL Insert, Update e Delete: Insert: Adicionam-se filas de dados em uma tabela: INSERT INTO NOMBTABELA [(COL [,COL]…)] VALUES (VALOR [,VALOR]…);
Nometabela= É a tabela na que se vão inserir as filas. Propriedades: Se as colunas não se especificam na cláusula Insert se consideram, por padrão, todas as colunas da tabela. As colunas às quais damos valores se identificam pelo seu nome. A associação coluna valor é posicional. Os valores que se dão às colunas devem coincidir com o tipo de dado definido na coluna. Os valores constantes de tipo caractere tem de ir fechados entre aspas simples (' ') (os de tipo data também). Com Select: •
• • •
•
Adicionam-se tantas filas como devolva a consulta: INSERT INTO NOMBTABELA [(COL [,COL]…)] SELECT {COLUNA [, COLUNA]… | *} FROM NOMETABELA2 [CLAUSULAS DE SELECT];
Update: Atualiza os valores das colunas para uma ou várias filas de uma tabela: UPDATE NOMETABELA SET COLUNA1= VALOR1, …, COLUNAN= VALORN WHERE CONDICAO;
Set= Indica as colunas que vão se atualizar e seus valores. Com Select: Quando a subconsulta (orden select) forma parte de SET, deve selecionar o mesmo número de colunas, (com tipos de dados adequados) que os que existem entre parênteses ao lado de SET. UPDATE NOMETABELA SET COLUNA= VALOR1, COLUNA2= VALOR2, … WHERE COLUNA3= (SELECT…)
OU UPDATE NOMETABELA Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
34
Manuais e recursos para desenvolvimento web www.criarweb.com SET (COLUNA1, COLUNA2, …)= (SELECT …) WHERE CONDICAO;
Delete: Elimina uma ou várias filas de uma tabela: DELETE [FROM] NOMETABELA WHERE CONDICAO;
Artigo por Agustin Jareño
Chaves primárias com SQL com Oracle Rollback: Permite ir até o último COMMIT feito ou em seu padrão até o começo das ordens com o que estas não se executam. Commit: Quando executamos ordens, estas não são criadas na tabela até que coloquemos esta ordem, portanto as mudanças realizadas se perderão se ao sair do programa não realizarmos esta ação. Pode se programar para que seja feito automaticamente. Algumas ordens que levam COMMIT implícito: • • • • • • • • • • • • •
QUIT EXIT CONNECT DISCONNECT CREATE TABLE CREATE VIEW GRANT REVOQUE DROP TABLE DROP VIEW ALTER AUDIT NO AUDIT
Criação de uma tabela: Seu primeiro caractere deve ser alfabético e o resto pode ser letras, números e o caractere sublinhado. CREATE TABLE NOMETABELA (COLUNA1 TIPO_DADO {NOT NULL}, COLUNA2 TIPO_DADO {NOT NULL}, … ) TABLESPACE ESPACO_DE_TABELA;
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
35
Manuais e recursos para desenvolvimento web www.criarweb.com
Características: • • •
As definições individuais de colunas se separam mediante vírgulas. Não se coloca vírgula depois da última definição de coluna. As maiúsculas e minúsculas são indiferentes.
Os usuários podem consultar as tabelas criadas por meio da vista USER_TABLES. Integridade de dados: A integridade faz referência ao fato de que os dados do banco de dados têm que se ajustar às restrições antes de se armazenar nele. Uma restrição de integridade será: Uma regra que restringe classe de valores para uma ou mais colunas na tabela. Restrições em create table: Usamos a cláusula CONSTRAINT, que pode restringir uma só coluna ou um grupo de colunas de uma mesma tabela. Existem dois modos de especificar restrições: Como parte da definição de colunas. Afinal, uma vez especificadas todas as colunas. Formato: • •
CREATE TABLE NOME_TABELA (COLUNA1 TIPO_DE_DADO {CONSTRAINT NOME_RESTRICAO} {NOT NULL} {UNIQUE} {PRIMARY KEY} {DEFAULT VALOR} {REFERENCES NOMETABELA [(COLUNA, [,COLUNA]) {ON DELETE CASCADE}} {CHECK CONDICAO}, COLUNA2... ) {TABLESPACE ESPACO_DE_TABELA} ; CREATE TABLE NOME_TABELA (COLUNA1 TIPO_DADO , COLUNA2 TIPO_DADO, COLUNA3 TIPO_DADO, ... {CONSTRAINT NOMERESTRICAO} [{UNIQUE} | {PRIMARY KEY} (COLUNA [, COLUNA])], {CONSTRAINT NOMERESTRICAO} {FOREIGN KEY (COLUNA [, COLUNA]) REFERENCES NOMETABELA {(COLUNA [, COLUNA]) {ON DELETE CASCADE}}, {CONSTRINT NOMERESTRICAO} {CHECK (CONDICAO)} … )[TABLESPACE ESPACO_DE_TABELA];
Artigo por Agustin Jareño
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
36
Manuais e recursos para desenvolvimento web www.criarweb.com
Definição de chaves para tabelas e restrições Chave primária: Primary key É uma coluna ou um conjunto de colunas que identificam univocamente a cada fila. Deve ser única, não nula e obrigatória. Como máximo, podemos definir uma chave primária por tabela. Esta chave pode ser referenciada por uma coluna ou colunas. Quando se cria uma chave primária, automaticamente se cria um índice que facilita o acesso à tabela. Formato de restrição de coluna: CREATE TABLE NOME_TABELA (COL1 TIPO_DADO [CONSTRAINT NOME_RESTRICAO] PRIMARY KEY COL2 TIPO_DADO … )[TABLESPACE ESPACO_DE_TABELA];
Formato de restrição de tabela: CREATE TABLE NOME_TABELA (COL1 TIPO_DADO, COL2 TIPO_DADO,
… [CONSTRAINT NOMERESTRICAO] PRIMARY KEY (COLUNA [,COLUNA]), … )[TABLESPACE ESPACO_DE_TABELA];
Chaves alheias: Foreign Key: Está formada por uma ou várias colunas que estão associadas a uma chave primária de outra ou da mesma tabela. Pode-se definir tantas chaves alheias quantas se necessite, e podem estar ou não na mesma tabela que a chave primária. O valor da coluna ou colunas que são chaves alheias deve ser: NULL ou igual a um valor da chave referenciada (regra de integridade referencial). Formato de restrição de coluna: CREATE TABLE NOME_TABELA (COLUNA1 TIPO_DADO [CONSTRAINT NOMERESTRICAO] REFERENCES NOMETABELA [(COLUNA)] [ON DELETE CASCADE] … )[TABLESPACE ESPACO_DE_TABELA];
Formato de restrição de tabela: CREATE TABLE NOME_TABELA (COLUNA1 TIPO_DADO, COLUNA2 TIPO_DADO, … [CONTRAINT NOMERESTRICAO] FOREIGN KEY (COLUNA [,COLUNA]) REFERENCES NOMETABELA [(COLUNA [, COLUNA])] [ON DELETE CASCADE], )[TABLESPACE ESPACO_DE_TABELA];
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
37
Manuais e recursos para desenvolvimento web www.criarweb.com
Notas: • • •
•
Na cláusula REFERENCES indicamos a tabela a qual remite a chave alheia. Há que criar primeiro uma tabela e depois aquela que lhe faz referência. Há que apagar primeiro a tabela que faz referência a outra tabela e depois a tabela que não faz referência. Eliminado em cascata (ON DELETE CASCADE): Se eliminarmos uma fila de uma tabela mãe, todas as filas da tabela detalhe cuja chave alheia seja referenciada se eliminarão automaticamente. A restrição se declara na tabela detalhe. A mensagem "n filas eliminadas" só indica as filas eliminadas da tabela mãe.
NOT NULL: Significa que a coluna não pode ter valores nulos. DEFAULT: Proporcionamos a uma coluna um valor padrão quando o valor da coluna não se especifica na cláusula INSERT. Na especificação DEFAULT é possível incluir várias expressões: constantes, funções SQL e variáveis UID e SYSDATE. Verificação de restrições: CHECK: Atua como uma cláusula where. Pode fazer referência a uma ou mais colunas, porém não a valores de outras filas. Em uma cláusula CHECK não se podem incluir sub-consultas nem as pseudo-consultas SYSDATE, UID e USER. Nota: A restrição NOT NULL é similar a CHECK (NOME_COLUNA IS NOT NULL)
UNIQUE: Evita valores repetidos na mesma coluna. Pode conter uma ou várias colunas. É similar à restrição PRIMARY KEY, salvo que são possíveis várias colunas UNIQUE definidas em uma tabela. Admite valores NULL. Assim como em PRIMARY KEY, quando se define uma restrição UNIQUE se cria um índice automaticamente. Vistas do dicionário de dados para as restrições: Contém informação geral as seguintes: USER_CONSTRAINTS: Definições de restrições de tabelas propriedade do usuário. ALL_CONSTRAINTS: Definições de restrições sobre tabelas as quais pode acessar o usuário. DBA_CONSTRAINTS: Todas as definições de restrições sobre todas as tabelas. Criação de uma tabela com dados recuperados em uma consulta: CREATE TABLE: permite criar uma tabela a partir da consulta de outra tabela já existente. A nova tabela conterá os dados obtidos na consulta. Realiza-se esta ação com a cláusula AS colocada ao final da ordem CREATE TABLE. CREATE TABLE NOMETABELA (COLUNA [,COLUNA] )[TABLESPACE ESPACO_DE_TABELA] AS CONSULTA;
Não é necessário especificar tipos nem tamanho das consultas, já que vêm determinadas pelos tipos e os tamanhos das recuperadas na consulta. A consulta pode ter uma sub-consulta, uma combinação de tabelas ou qualquer sentença select válida. As restrições COM NOME não se criam em uma tabela desde a outra, só se criam aquelas restrições que carecem de nome.
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
38
Manuais e recursos para desenvolvimento web www.criarweb.com
Artigo por Agustin Jareño
Supressão e modificação de tabelas com SQL Supressão de tabelas: DROP TABLE: suprime uma tabela do banco de dados. Cada usuário pode eliminar suas próprias tabelas, porém só o administrador ou algum usuário com o privilégio "DROP ANY TABLE" pode eliminar as tabelas de outro usuário. Ao suprimir uma tabela também se suprimem os índices e os privilégios associados a ela. As vistas e os sinônimos criados a partir desta tabela deixam de funcionar, mas continuam existindo no banco de dados, portanto deveríamos elimina-los. Exemplo: DROP TABLE [USUARIO].NOMETABELA [CASCADE CONSTRAINTS];
TRUNCATE: permite suprimir todas as filas de uma tabela e liberar o espaço ocupado para outros usos sem que reapareça a definição da tabela do banco de dados. Uma ordem TRUNCATE não se pode anular, assim como também não ativa os disparadores DELETE. TRUNCATE TABLE [USUARIO.]NOMETABELA [{DROP | REUSE} STORAGE];
Modificação de tabelas: Modificam-se as tabelas de duas formas: Mudando a definição de uma coluna (MODIFY) ou acrescentando uma coluna a uma tabela existente (ADD): Formato: ALTER TABLE NOMETABELA {[ADD (COLUNA [,COLUNA]…)] [MODIFY (COLUNA [,COLUNA]…)] [ADD CONSTRAINT RESTRICAO] [DROP CONSTRAINT RESTRICAO]};
ADD= Adiciona uma coluna ou mais no final de uma tabela. MODIFY= Modifica uma ou mais colunas existentes na tabela. ADD CONSTRAINT= Adiciona uma restrição à definição da tabela. DROP CONSTRAINT= Elimina uma restrição da tabela. Na hora de adicionar uma coluna a uma tabela há que ter em conta: •
Se a coluna não estiver definida como NOT NULL pode-se adicionar em qualquer momento.
Se a coluna estiver definida como NOT NULL pode-se seguir estes passos: 1. Adiciona-se uma coluna sem especificar NOT NULL. 2. Dá-se valor à coluna para cada uma das filas. 3. Modifica-se a coluna NOT NULL. Ao modificar uma coluna de uma tabela, há que ter em conta: •
•
•
Pode-se aumentar a longitude de uma coluna em qualquer momento. É possível aumentar ou diminuir o número de posições decimais em uma coluna de tipo
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
39
Manuais e recursos para desenvolvimento web www.criarweb.com
NUMBER. •
•
Se a coluna for NULL em todas as filas da tabela, pode-se diminuir a longitude e modificar o tipo de dado. A opção MODIFY… NOT NULL só será possível quando a tabela não contiver nenhuma fila com valor nulo na coluna que se modifica.
Adição de restrições: Com a ordem ALTER TABLE se acrescentam restrições a uma tabela. Formato: ALTER TABLE NOMETABELA ADD CONSTRAINT NOMECONSTRAINT…
Eliminação de restrições: A ordem ALTER TABLE com a cláusula DROP CONSTRAINT; com a que se eliminam as restrições com nome e as atribuídas pelo sistema. Formato: ALTER TABLE NOMETABELA DROP CONSTRAINT NOME_CONSTRAINT, NOME_RESTRICAO:
Artigo por Agustin Jareño
Gerenciamento de vistas em SQL Criação e uso de vistas Não contém informação por si mesmas, e sim, estão baseadas nas que contém outras tabelas e reflete os dados destas. Se se suprime uma tabela a vista associada se invalida. Formato: CREATE [OR REPLACE] VIEW NOMEVISTA [(COLUNA [,COLUNA])] AS CONSULTA;
AS CONSULTA= Determina as colunas e as tabelas que aparecerão na vista. [OR REPLACE]= Cria de novo a vista se já existia. Para consultar a vista criada, USER_VIEWS: SELECT VIEW_NAME FROM… Nota: ao eliminar as tabelas, as vistas dessas tabelas não se eliminam e ficam inutilizadas.
Eliminação de vistas Faz-se com DROP VIEW. Formato: DROP VIEW NOMEVISTA; Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
40
Manuais e recursos para desenvolvimento web www.criarweb.com
Operações sobre vistas Pode-se realizar as mesmas operações que se fazem sobre as tabelas. Restrições: •
• •
Atualização. Se uma vista está baseada em uma só tabela, pode-se modificar as filas da vista. A modificação da vista muda a tabela sobre a qual está definida. Eliminação de filas através de uma vista= Para eliminar filas de uma tabela através de uma vista, esta se deve criar: Com filas de uma só tabela. Sem utilizar a cláusula GROUP BY nem DISTINCT. Sem usar funções de grupo ou referências a pseudo-colunas. Atualização de filas através de uma vista: Para atualizar filas em uma tabela através de uma vista, esta tem que estar definida segundo as restrições anteriores e, ademais, nenhuma das colunas que vai se atualizar terá definido como uma expressão. Inserção de filas através de uma vista: Para inserir filas em uma tabela através de uma vista, há que ter em conta todas as restrições anteriores e, ademais, todas as colunas obrigatórias da tabela associada devem estar presentes na vista. Manejo de expressões e de funções em vistas: Pode-se criar vistas usando funções, expressões em colunas e consultas avançadas, porém unicamente se emparelham consultar estas vistas. Também podemos modificar filas sempre e quando a coluna que vai se modificar não for a coluna expressada em forma de cálculo ou com funções. • • •
•
•
•
Nota: Não é possível inserir filas se as colunas da vista contém cálculos ou funções.
Mudanças de nome RENAME muda o nome de uma tabela, vista ou sinônimo. O novo nome não pode ser uma palavra reservada no nome de um objeto que o usuário tiver criado. As restrições de integridade, os índices e as permissões dadas ao objeto se transferem automaticamente ao novo objeto. REANME NOME_ANTERIOR TO NOME_NOVO;
Com esta ordem não podemos re-nomear colunas de uma tabela, estas se re-nomeiam mediante CREATE TABLE AS… Artigo por Agustin Jareño
Usuários em Oracle É um nome definido no banco de dados que se pode conecta-lo e acessar a determinados objetos segundo certas condições que o administrador estabelece. Os objetos do dicionário de dados aos que um usuário pode acessar, encontram-se na vista DICTIONARY, que é propriedade do usuário SYS. DESC DICTIONARY;
Com a ordem: Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
41
Manuais e recursos para desenvolvimento web www.criarweb.com
SELECT TABLENAME FROM DICTIONARY;
Visualizam-se os objetos do dicionário de dados aos que se pode acessar. Criação de usuários: CREATE USER NOME_USUARIO IDENTIFIED BY SENHA_ACESSO [DEFAULT TABLESPACE ESPACO_TABELA] [TEMPORARY TABLESPACE ESPACO_TABELA] [COTA {INTEIRO {K | M} | UNLIMITED } ON ESPACO_TABELA] [PROFILE PERFIL];
DEFAULT TABLESPACE= Atribui a um usuário o tablespace padrão para armazenar os objetos que crie. Se não se atribui nenhum, o tablespace padrão é SYSTEM. TEMPORARY TABLESPACE= Especifica o nome do tablespace para trabalhar temporais. Se não se especifica nenhum, o tablespace padrão é SYSTEM. QUOTA= Atribui um espaço em megabites ou kilobites no tablespace atribuído. Se não se especifica esta cláusula, o usuário não tem cota atribuída e não poderá criar objetos no tablespace. Para ter espaço e acesso ilimitado a um tablespace é: GRANT UNLIMITED TABLESPACE NOME_TABLESPACE;
PROFILE= Atribui um perfil a um usuário. Modificação de usuários: ALTER USER NOME_USUARIO IDENTIFIED BY SENHA _ACESSO [DEFAULT TABLESPACE ESPACO_TABELA] [TEMPORARY TABLESPACE ESPACO_TABELA] [COTA {INTEIRO {K | M } | UNLIMITED } ON ESPACO_TABELA [PROFILE PERFIL];
Eliminação de usuarios: DROP USER USUARIO [CASCADE];
CASCADE= Suprime todos os objetos do usuário antes de elimina-lo. Artigo por Agustin Jareño
Gerenciamento em Oracle com SQL Privilégios é a capacidade de um usuário dentro do banco de dados a realizar determinadas operações ou acessar a determinados objetos de outros usuários. Privilégios sobre os objetos
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
42
Manuais e recursos para desenvolvimento web www.criarweb.com
Permite-nos acessar e realizar mudanças nos dados de outros usuários. Exemplo: O privilégio de consultar a tabela de outro usuário é um privilégio sobre objetos. GRANT {PRIV_OBJETO [, PRIV_OBJETO]… | ALL [PRIVILEGES]} [(COL [,COL]…)] ON [USUARIO] OBJETO TO {USUARIO | ROL | PUBLIC} [,{USUARIO | ROL | PUBLIC}…] [WITH GRANT OPTION];
ON= Especifica o objeto sobre o qual se dão os privilégios. TO= Identifica aos usuários ou rols aos quais se concedem os privilégios. ALL= Concede todos os privilégios sobre o objeto especificado. WITCH GRANT OPTION= Permite que o receptor do privilégio ou rol se atribua a outros usuários ou rols. PUBLIC= Atribui os privilégios a todos os usuários atuais e futuros: O propósito principal do grupo PUBLIC é garantir o acesso a determinados objetos a todos os usuários do banco de dados. Privilégios de sistema Dão direito a executar um tipo de comando SQL ou a realçar alguma ação sobre objetos de um tipo especificado. Por exemplo, o privilégio para criar TABLESPACES é um privilégio de sistema. Formato: GRANT {PRIVILEGIO | ROL} [, {PRIVILEGIO | ROL}, …] TO {USUARIO | ROL | PUBLIC} [,{USUARIO | ROL | PUBLIC}] [WITH ADMIN OPTION];
WITH ADMIN OPTION= Permite que o receptor do privilégio ou rol possa conceder esses mesmos privilégios a outros usuários ou rols. Retirada de privilégios de objetos aos usuários REVOKE {PRIV_OBJETO [,PRIV_OBJETO]… | ALL [PRIVILEGES]} ON [USUARIO.]OBJETO FROM {USUARIO | ROL | PUBLIC} [, {USUARIO | ROL | PUBLIC}]…;
Retirada de privilégios de sistema ou rols aos usuários REVOKE {PRIV_SISTEMA | ROL} [,{PRIV_SISTEMA | ROL}]… FROM {USUARIO | ROL | PUBLIC} [,{USUARIO | ROL | PUBLIC}]…;
Roles Conjunto de privilégios agrupados. Formato: CREATE ROLE NOMEROL [IDENTIFIED BY SENHA]; Nota: Um rol pode decidir o acesso de um usuário a um objeto, mas não pode permitir a criação de objetos.
Supressão de privilégios nos roles REVOKE NOMEPRIVILEGIO ON NOMETABELA FROM NOMEROL; Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
43
Manuais e recursos para desenvolvimento web www.criarweb.com
REVOKE NOMEPRIVILEGIO FROM NOMEROL;
Supressão de um rol DROP ROLE NOMEROL;
Estabelecer um rol padrão ALTER USER NOMEUSUARIO DEFAULT {[ROLE NOME_ROL] | [NONE]};
NONE= Faz com que o usuário não tenha rol padrão. Perfis: Conjunto de limites aos recursos do banco de dados: CREATE PROFILE NOMEPERFIL LIMIT {NOME DOS LIMITES} {INTEIRO [K | M] | UNLIMITED | DEFAULT };
UNLIMITED= Não há limites sobre um recurso em particular. DEFAULT= Pega o limite do perfil default. Eliminação de um perfil: DROP FILE NOMEPERFIL [CASCADE];
Gerenciamento de tablespaces Um tablespace é uma unidade lógica de armazenamento de dados representada fisicamente por um ou mais arquivos de dados. Recomenda-se não misturar dados de diferentes aplicações em um mesmo tablespace. Para criar um tablespace CREATE TABLESPACE NOMETABLESPACE DATAFILE 'NOMEARQUIVO' [SIZE INTEIRO [K | M] [REUSE] [DEFAULT STORAGE (INITIAL TAMANHO MINEXTENTS TAMANHO MAXEXTENTS TAMANHO PCTINCREASE VALOR )] [ONLINE | OFFLINE];
REUSE= Reutiliza o arquivo se já existe ou o cria se não existe. DEFAULT STORAGE= Define o armazenamento por omissão para todos os objetos que se criam neste espaço da tabela. Observe a quantidade de espaço se não se especifica na sentença CREATE TABLE. Modificação de tablespaces ALTER TABLESPACE NOMETABLESPACE Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
44
Manuais e recursos para desenvolvimento web www.criarweb.com {[ADD DATAFILE 'NOMEARQUIVO' [SIZE INTEIRO [K | M] [REUSE] [AUTOEXTEND ON… | OFF] ] [REANME DATAFILE 'ARQUIVO' [, 'ARQUIVO']… TO 'ARQUIVO' [, 'ARQUIVO']] [DEFAULT STORAGE CLAUSULAS_ARMAZENAMENTO] [ONLINE | OFFLINE] };
ADD_DATAFILE= Adiciona ao tablespace um ou vários arquivos. AUTOEXTEND= Ativa ou desativa o crescimento automático dos arquivos de dados do tablespace. Quando um tablespace se enche podemos usar esta opção para que o tamanho do arquivo ou arquivos de dados associados cresça automaticamente. Autoextend off: desativa o crescimento automático. RENAME_DATAFILE= Muda o nome de um arquivoe existente do tablespace. Esta mudança tem que ser feita através do sistema operacional e, depois, executar a ordem SQL. Eliminação de tablespaces DROP TABLESPACE NOMETABLESPACE [INCLUDING CONTENTS];
INCLUDING CONTENTS= Permite eliminar um tablespace que tenha dados. Sem esta opção só se pode suprimir um tablespace vazio. Recomenda-se colocar o talespace offline antes de elimina-lo para certificarmos de que não haja sentenças SQL que estejam acessando dados do tablespace, em cujo caso não seria possível elimina-lo. Quando se elimina um tablespace os arquivos associados não se apagam do sistema operacional, portanto teremos que elimina-los de forma manual. Artigo por Agustin Jareño
Otimizar consultas SQL A linguagem SQL é não procedimental, ou seja, nas sentenças se indica o que queremos conseguir e não como tem que fazer o intérprete para consegui-lo. Isto é pura teoria, pois na prática todos os gerenciadores de SQL têm que especificar seus próprios truques para otimizar o rendimento. Portanto, muitas vezes não basta com especificar uma sentença SQL correta, e sim que além disso, há que indicar como tem que fazer se quisermos que o tempo de resposta seja o mínimo. Nesta seção, veremos como melhorar o tempo de resposta de nosso intérprete ante umas determinadas situações: Design de tabelas •
•
Normalize as tabelas, pelo menos até a terceira forma normal, para garantir que não haja duplicidade de dados e aproveitar o máximo de armazenamento nas tabelas. Se tiver que desnormalizar alguma tabela pense na ocupação e no rendimento antes de proceder. Os primeiros campos de cada tabela devem ser aqueles campos requeridos e dentro dos requeridos primeiro se definem os de longitude fixa e depois os de longitude
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
45
Manuais e recursos para desenvolvimento web www.criarweb.com
variável. Ajuste ao máximo o tamanho dos campos para não desperdiçar espaço. É normal deixar um campo de texto para observações nas tabelas. Se este campo for utilizado com pouca freqüência ou se for definido com grande tamanho, por via das dúvidas, é melhor criar uma nova tabela que contenha a chave primária da primeira e o campo para observações. Gerenciamento e escolha dos índices • •
Os índices são campos escolhidos arbitrariamente pelo construtor do banco de dados que permitem a busca a partir de tal campo a uma velocidade notavelmente superior. Entretanto, esta vantagem se vê contra-arrestada pelo fato de ocupar muito mais memória (o dobro mais ou menos) e de requerer para sua inserção e atualização um tempo de processo superior. Evidentemente, não podemos indexar todos os campos de uma tabela extensa já que dobramos o tamanho do banco de dados. Igualmente, tampouco serve muito indexar todos os campos em uma tabela pequena já que as seleções podem se efetuar rapidamente de qualquer forma. Um caso em que os índices podem ser muito úteis é quando realizamos petições simultâneas sobre várias tabelas. Neste caso, o processo de seleção pode se acelerar sensivelmente se indexamos os campos que servem de nexo entre as duas tabelas. Os índices podem ser contraproducentes se os introduzimos sobre campos triviais a partir dos quais não se realiza nenhum tipo de petição já que, além do problema de memória já mencionado, estamos lentificando outras tarefas do banco de dados como são a edição, inserção e eliminação. É por isso que vale a pena pensar duas vezes antes de indexar um campo que não serve de critério para buscas ou que é usado com muita freqüência por razões de manutenção. Campos a Selecionar Na medida do possível há que evitar que as sentenças SQL estejam embebidas dentro do código da aplicação. É muito mais eficaz usar vistas ou procedimentos armazenados por que o gerenciador os salva compilados. Se se trata de uma sentença embebida o gerenciador deve compila-la antes de executa-la. Selecionar exclusivamente aqueles que se necessitem Não utilizar nunca SELECT * porque o gerenciador deve ler primeiro a estrutura da tabela antes de executar a sentença Se utilizar várias tabelas na consulta, especifique sempre a que tabela pertence cada campo, isso economizará tempo ao gerenciador de localizar a que tabela pertence o campo. Ao invés de SELECT Nome, Fatura FROM Clientes, Faturamento WHERE IdCliente = IdClienteFaturado, use: SELECT Clientes.Nome, Faturamento.Fatura WHERE Clientes.IdCliente = Faturamento.IdClienteFaturado. Campos de Filtro •
• •
•
•
• •
Procuraremos escolher na cláusula WHERE aqueles campos que fazem parte da chave do arquivo pelo qual interrogamos. Ademais se especificarão na mesma ordem na qual estiverem definidas na chave. Interrogar sempre por campos que sejam chave. Se desejarmos interrogar por campos pertencentes a índices compostos é melhor utilizar todos os campos de todos os índices. Suponhamos que temos um índice formado pelo campo NOME e o campo SOBRENOME e outro índice formado pelo campo
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
46
Manuais e recursos para desenvolvimento web www.criarweb.com
IDADE. A sentença WHERE NOME='Jose' AND SOBRENOME Like '%' AND IDADE = 20 seria melhor que WHERE NOME = 'Jose' AND IDADE = 20 porque o gerenciador, neste segundo caso, não pode usar o primeiro índice e ambas sentenças são equivalentes porque a condição SOBRENOME Like '%' devolveria todos os registros. Ordem das Tabelas Quando se utilizam várias tabelas dentro da consulta há que ter cuidado com a ordem empregada na cláusula FROM. Se desejarmos saber quantos alunos se matricularam no ano 1996 e escrevermos: FROM Alunos, Matriculas WHERE Aluno.IdAluno = Matriculas.IdAluno AND Matriculas.Ano = 1996 o gerenciador percorrerá todos os alunos para buscar suas matrículas e devolver as correspondentes. Se escrevermos FROM Matriculas, Alunos WHERE Matriculas.Ano = 1996 AND Matriculas.IdAluno = Alunos.IdAlunos, o gerenciador filtra as matrículas e depois seleciona os alunos, desta forma tem que percorrer menos registros. Artigo por Claudio
Consultas de seleção Este conjunto de registros pode ser modificável. Consultas básicas A sintaxe básica de uma consulta de seleção é a seguinte: SELECT Campos FROM Tabela
Onde "campos" é a lista de campos que se deseja recuperar e "tabela" é a origem dos mesmos, por exemplo: SELECT Nombre, Telefone FROM Clientes
Esta sentença devolve um conjunto de resultados com o campo nome e telefone da tabela clientes. Devolver Literais Em determinadas ocasiões pode nos interessar incluir uma coluna com um texto fixo em uma consulta de seleção, por exemplo, suponhamos que temos uma tabela de empregados e desejamos recuperar as tarifas semanais dos eletricistas, poderíamos realizar a seguinte consulta: SELECT Empregados.Nome, 'Tarifa semanal: ', Empregados.TarifaHora * 40 FROM Empregados WHERE Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
47
Manuais e recursos para desenvolvimento web www.criarweb.com Empleados.Cargo = 'Eletricista'
Ordenar los registros Adicionalmente pode se especificar a ordem em que se deseja recuperar os registros das tabelas mediante a cláusula ORDER BY Lista de Campos. Em onde Lista de campos representa os campos a ordenar. Exemplo: SELECT CodigoPostal, Nome, Telefone FROM Clientes ORDER BY Nome
Esta consulta devolve os campos CodigoPostal, Nome, Telefone da tabela Clientes ordenados pelo campo Nome. Pode-se ordenar os registros por mais de um campo, como por exemplo: SELECT CodigoPostal, Nome, Telefone FROM Clientes ORDER BY CodigoPostal, Nome
Inclusive pode-se especificar a ordem dos registros: ascendente mediante a cláusula (ASC toma-se este valor padrão) ou descendente (DESC) SELECT CodigoPostal, Nome, Telefone FROM Clientes ORDER BY CodigoPostal DESC , Nome ASC
Uso de Índices das tabelas Se desejarmos que a sentença SQL utilize um índice para mostrar os resultados se pode utilizar a palavra reservada INDEX da seguinte forma: SELECT ... FROM Tabela (INDEX=Indice) ...
Normalmente os motores dos bancos de dados decidem que índice se deve utilizar para a consulta, para isso utilizam critérios de rendimento e sobretudo, os campos de busca especificados na cláusula WHERE. Se se deseja forçar a não utilizar nenhum índice utilizaremos a seguinte sintaxe: SELECT ... FROM Tabela (INDEX=0) ...
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
48
Manuais e recursos para desenvolvimento web www.criarweb.com
Consultas com Predicado O predicado se inclui entre a cláusula e o primeiro nome do campo a recuperar, os possíveis predicados são: Predicado Descrição ALL
Devolve todos os campos da tabela
TOP
Devolve um determinado número de registros da tabela
DISTINCT Omite os registros cujos campos selecionados coincidam totalmente DISTINCTO Omite os registros duplicados baseando-se na totalidade do registro e não só W nos campos selecionados. ALL Se não se inclui nenhum dos predicados se assume ALL. O Motor de banco de dados seleciona todos os registros que cumprem as condições da instrução SQL e devolve todos e cada um de seus campos. Não é conveniente abusar deste predicado já que obrigamos ao motor do banco de dados a analisar a estrutura da tabela para averiguar os campos que contém, é muito mais rápido indicar a lista de campos desejados. SELECT ALL FROM Empregados SELECT * FROM Empregados
TOP Devolve um certo número de registros que entram entre ao princípio ou ao final de uma categoria especificada por uma cláusula ORDER BY. Suponhamos que queremos recuperar os nomes dos 25 primeiros estudantes do curso 1994: SELECT TOP 25 Nome, Sobrenome FROM Estudantes ORDER BY Nota DESC
Se não se inclui a cláusula ORDER BY, a consulta devolverá um conjunto arbitrário de 25 registros da tabela de Estudantes. O predicado TOP não escolhe entre valores iguais. No exemplo anterior, se a nota média número 25 e a 26 são iguais, a consulta devolverá 26 registros. Pode-se utilizar a palavra reservada PERCENT para devolver uma certa porcentagem de registros que caem ao princípio ou ao final de uma categoria especificada pela cláusula ORDER BY. Suponhamos que no lugar dos 25 primeiros estudantes desejamos o 10 por cento do curso: Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
49
Manuais e recursos para desenvolvimento web www.criarweb.com
SELECT TOP 10 PERCENT Nome, Sobrenome FROM Estudantes ORDER BY Nota DESC
O valor que vai a seguir de TOP deve ser um inteiro sem signo. TOP não afeta à possível atualização da consulta. DISTINCT Omite os registros que contém dados duplicados nos campos selecionados. Para que os valores de cada campo listado na instrução SELECT se incluam na consulta devem ser únicos. Por exemplo, vários empregados listados na tabela Empregados podem ter o mesmo sobrenome. Se dois registros contém Lopez no campo Sobrenome, a seguinte instrução SQL devolve um único registro: SELECT DISTINCT Sobrenome FROM Empregados
Com outras palavras o predicado DISTINCT devolve aqueles registros cujos campos indicados na cláusula SELECT possuam um conteúdo diferente. O resultado de uma consulta que utiliza DISTINCT não é atualizável e não reflete as mudanças subseqüentes realizadas por outros usuários. DISTINCTROW Este predicado não é compatível com ANSI. Que eu saiba no dia de hoje só funciona com ACCESS. Devolve os registros diferentes de uma tabela; a diferença do predicado anterior que só se fixava no conteúdo dos campos selecionados, este o faz no conteúdo do registro completo independentemente dos campos indicados na cláusula SELECT. SELECT DISTINCTROW Sobrenome FROM Empregados
Se a tabela empregados contém dois registros: Antonio Lopez e Marta Lopez o exemplo do predicado DISTINCT devolve um único registro com o valor Lopez no campo Sobrenome já que busca não duplicados em tal campo. Este último exemplo devolve dois registros com o valor Lopez no sobrenome já que se buscam não duplicados no registro completo. ALIAS Em determinadas circunstâncias é necessário atribuir um nome a alguma coluna determinada de um conjunto devolvido, outras vezes por simples capricho ou porque estamos recuperando dados de diferentes tabelas e acabam tendo um campo com igual nome. Para resolver todas elas, temos a palavra reservada AS que se encarrega de atribuir o nome que desejamos à coluna desejada. Tomado como referência o exemplo anterior podemos fazer a coluna devolvida pela consulta, ao invés de se chamar sobrenome (assim como o campo devolvido) se Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
50
Manuais e recursos para desenvolvimento web www.criarweb.com
chame Empregado. Neste caso procederíamos da seguinte forma: SELECT DISTINCTROW Sobrenome AS Empregado FROM Empregados
AS não é uma palavra reservada de ANSI, existem diferentes sistemas de atribuir os alias em função do motor de banco de dados. Em ORACLE para atribuir um alias a um campo há que fazer da seguinte forma: SELECT Sobrenome AS "Empregado" FROM Empregados
Também podemos atribuir alias às tabelas dentro da consulta de seleção, neste caso há que ter em conta que em todas as referências que desejarmos fazer a tal tabela há que utilizar o alias ao invés do nome. Esta técnica será de grande utilidade mais adiante quando se estudarem as vinculações entre tabelas. Por exemplo: SELECT Apellido AS Empregado FROM Empregados AS Trabalhadores
Para atribuir alias às tabelas em ORACLE e SQL-SERVER os alias se atribuem escrevendo o nome da tabela, deixando um espaço em branco e escrevendo o Alias (se atribuem dentro da cláusula FROM). SELECT Trabalhadores.Sobrenome (1) AS Empregado FROM Empregadore Trabalhadores
(1)Esta nomenclatura [Tabela].[Campo] deve-se utilizar quando se está recuperando um campo cujo nome se repete em várias das tabelas que se utilizam na sentença. Não obstante quando na sentença se empregam várias tabelas é aconselhável utilizar esta nomenclatura para evitar o trabalho que supõem ao motor de dados averiguar em que tabela está cada um dos campos indicados na cláusula SELECT. Recuperar Informação de um banco de Dados Externo Para concluir este capítulo se deve fazer referência à recuperação de registros de banco de dados externos. Em ocasiões é necessário a recuperação de informação que se encontra contida em uma tabela que não se encontra no banco de dados que executará a consulta ou que nesse momento não se encontra aberta, esta situação podemos salva-la com a palavra reservada IN da seguinte forma: SELECT Sobrenome AS Empregado FROM Empleados IN'c: \databases\gerenciamento.mdb'
Em onde c: \databases\gerenciamento.mdb é o banco de dados que contém a tabela Empregados. Esta técnica é muito simples e comum em banco de dados do tipo ACCESS em outros sistemas como SQL-SERVER ou ORACLE, a cosa é mais complicada por ter que existir relações de confiança entre os servidores ou ao ser necessária a vinculação entre os banco de Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
51
Manuais e recursos para desenvolvimento web www.criarweb.com
dados. Este exemplo recupera a informação de um banco de dados de SQL-SERVER localizado em outro servidor (obviamente que os servidores estão linkados): SELECT Sobrenome FROM Servidor1.BancoDados1.dbo.Empregados
Artigo por Claudio
Critérios de seleção em SQL Na seção anterior vimos a forma de recuperar os registros das tabelas, as formas empregadas devolviam todos os registros da mencionada tabela. Ao longo deste manual se estudarão as possibilidades de filtrar os registros com o fim de recuperar somente aqueles que cumpram umas condições pré-estabelecidas. Antes de começar o desenvolvimento deste artigo, há que ressaltar três detalhes de vital importância. O primeiro deles é que cada vez que se deseja estabelecer uma condição referida a um campo de texto a condição de busca deve ir fechada entre aspas simples; a segunda é que não é possível estabelecer condições de busca nos campos memo e; a terceira e última faz referência às datas. Ate hoje não fui capaz de encontrar uma sintaxe que funcione em todos os sistemas, por isso se faz necessário particulariza-las segundo o banco de dados: Banco de Datos
Sintaxe
SQL-SERVER
Data = #mm-dd-aaaa#
ORACLE
Data = to_date('YYYYDDMM','aaaammdd',)
ACCESS
Fecha = #mm-dd-aaaa# Exemplo
Banco de Dados Exemplo (para gravar a data 18 de maio de 1969) SQLSERVER
Data = #05-18-1969# ó Data = 19690518
ORACLE
Data = to_date('YYYYDDMM', '19690518')
ACCESS
Data = #05-18-1969#
Referente aos valores lógicos True ou False cabe destacar que não são reconhecidos em ORACLE, nem nesse sistema de banco de dados, nem em SQL-SERVER existem os campos de Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
52
Manuais e recursos para desenvolvimento web www.criarweb.com
tipo "SIM/NAO" de ACCESS; nesses sistemas se utilizam os campos BIT que permitem armazenar valores de 0 ou 1. Internamente, ACCESS, armazena neste campos valores de 0 ou -1, por tanto tudo se complica bastante, porém, aproveitando a coincidência do 0 para os valores FALSE, pode-se utilizar a sintaxe seguinte que funciona em todos os casos: se se deseja saber se o campo é falso "... CAMPO = 0" e para saber os verdadeiros "CAMPO <> 0". Operadores Lógicos Os operadores lógicos suportados por SQL são: AND, OR, XOR, Eqv, Imp, Is e Not. Com exceção dos dois últimos, todos possuem a seguinte sintaxe:
operador
Onde expressao1 e expressao2 são as condições a avaliar, o resultado da operação varia em função do operador lógico. A tabela anexa mostra os diferentes possíveis resultados:
Operador
Resultado
Verdadeiro
AND
Falso
Falso
Verdadeiro
AND
Verdadeiro
Verdadeiro
Falso
AND
Verdadeiro
Falso
Falso
AND
Falso
Falso
Verdadeiro
OR
Falso
Verdadeiro
Verdadeiro
OR
Verdadeiro
Verdadeiro
Falso
OR
Verdadeiro
Verdadeiro
Falso
OR
Falso
Falso
Verdadeiro
XOR
Verdadeiro
Falso
Verdadeiro
XOR
Falso
Verdadeiro
Falso
XOR
Verdadeiro
Verdadeiro
Falso
XOR
Falso
Falso
Verdadeiro
Eqv
Verdadeiro
Verdadeiro
Verdadeiro
Eqv
Falso
Falso
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
53
Manuais e recursos para desenvolvimento web www.criarweb.com
Falso
Eqv
Verdadeiro
Falso
Falso
Eqv
Falso
Verdadeiro
Verdadeiro
Imp
Verdadeiro
Verdadeiro
Verdadeiro
Imp
Falso
Falso
Verdadeiro
Imp
Null
Null
Falso
Imp
Verdadeiro
Verdadeiro
Falso
Imp
Falso
Verdadeiro
Falso
Imp
Null
Verdadeiro
Null
Imp
Verdadeiro
Verdadeiro
Null
Imp
Falso
Null
Null
Imp
Null
Null
Se a qualquer das anteriores condições lhe ante-pusermos o operador NOT o resultado da operação será o contrário ao devolvido sem o operador NOT. O último operador denominado Is se emprega para comparar duas variáveis de tipo objeto Is . este operador devolve verdadeiro se os dois objetos forem iguais. SELECT * FROM Empregados WHERE Idade > 25 AND Idade < 50 SELECT * FROM Empregados WHERE (Idade > 25 AND Idade < 50) OR Salario = 100 SELECT * FROM Empregados WHERE NOT Estado = 'Solteiro' SELECT * FROM Empregados WHERE (Salario >100 AND Salario < 500) OR Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
54
Manuais e recursos para desenvolvimento web www.criarweb.com (Cidade = 'Madri' AND Estado = 'Casado')
Intervalos de Valores Para indicar que desejamos recuperar os registros segundo o intervalo de valores de um campo empregaremos o operador Between cuja sintaxe é: campo [Not] Between valor1 And valor2 (a condição Not é opcional)
Neste caso a consulta devolveria os registros que contiverem em "campo" um valor incluído no intervalo valor1, valor2 (ambos inclusive). Se ante-pusermos a condição Not devolverá aquelos valores não incluídos no intervalo. SELECT * FROM Pedidos WHERE CodPostal Between 28000 And 28999 (Devolve os pedidos realizados na cidade de Madrid)
O Operador Like Utiliza-se para comparar uma expressão de cadeia com um modelo em uma expressão SQL. Sua sintaxe é: expressão Like modelo
Onde expressão é uma cadeia modelo ou campo contra o que se compara expressão. Pode-se utilizar o operador Like para encontrar valores nos campos que coincidam com o modelo especificado. Por modelo pode especificar um valor completo (Ana Maria), ou se pode utilizar uma cadeia de caracteres asterisco como os reconhecidos pelo sistema operacional para encontrar uma classificação de valores (Like An*). O operador Like pode ser utilizado em uma expressão para comparar um valor de um campo com uma expressão de cadeia. Por exemplo, se introduzirmos Like C* em uma consulta SQL, a consulta devolve todos os valores de campo que começarem pela letra C. Em uma consulta com parâmetros, pode fazer com que o usuário escreva o modelo que será utilizado. O exemplo seguinte devolve os dados que começam com a letra P seguido de qualquer letra entre A e F e de três dígitos: Like 'P[A-F]###'
Este exemplo devolve os campos cujo conteúdo comece com uma letra da A à D seguidas de qualquer cadeia. Like '[A-D]*'
Na tabela seguinte se mostra como utilizar o operador Like para comprovar expressões com diferentes modelos. ACCESS ' Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
55
Manuais e recursos para desenvolvimento web www.criarweb.com
Tipo de coincidência
Modelo Planejado
Coincidee
Varios caracteres
'a*a'
aa', 'aBa', 'aBBBa' 'aBC'
Caractere especial
'a[*]a'
'a*a'
'aaa'
Varios caracteres
'ab*'
'abcdefg', 'abc'
'cab', 'aab'
Um so caractere
'a?a'
'aaa', 'a3a', 'aBa' 'aBBBa'
Um so digito
'a#a'
'a0a', 'a1a', 'a2a' 'aaa', 'a10a'
Categoria de caracteres
'[a-z]'
'f', 'p', 'j'
'2', '&'
Fora de uma categoria '[!a-z]'
'9', '&', '%'
'b', 'a'
Diferente de um digito '[!0-9]'
'A', 'a', '&', '~'
'0', '1', '9'
Combinada
'An9', 'az0', 'a99' 'abc', 'aj0'
'a[!b-m]#'
Nao coincide
SQL-SERVER Exemplo
Descrição
LIKE 'A%'
Tudo que comecar por A
LIKE '_NG'
Tudo que comece por qualquer caractere e logo siga NG
LIKE '[AF]%' Tudo que comecar por A ou F LIKE '[A-F] %'
Tudo que comece por qualquer letra compreendida entre a A e a F
LIKE '[A^B] Tudo que comecar por A e a segunda letra nao for uma B %' Em determinado motores de banco de dados, esta cláusula, não reconhece o asterisco como caractere e há que substitui-lo pelo caractere tanto por cento (%). O Operador In Este operador devolve aqueles registros cujo campo indicado coincide com algum dos em uma lista. Sua sintaxe é: Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
56
Manuais e recursos para desenvolvimento web www.criarweb.com
expressao [Not] In(valor1, valor2, . . .) SELECT * FROM Pedidos WHERE Cidade In ('Madri', 'Barcelona', 'Sevilha')
A cláusula WHERE A cláusula WHERE pode ser usada para determinar que registros das tabelas enumeradas na cláusula FROM aparecerão nos resultados da instrução SELECT. Depois de escrever esta cláusula deve-se especificar as condições expostas nas seções anteriores. Se não se emprega esta cláusula, a consulta devolverá todas as filas da tabela. WHERE é opcional, mas quando aparece deve ir a seguir de FROM. SELECT Sobrenome, Salario FROM Empregados WHERE Salario = 21000 SELECT IdProduto, Existencias FROM Produtos WHERE Existencias <= NovoPedido SELECT * FROM Pedidos WHERE DataEnvio = #05-30-1994# SELECT Sobrenomes, Nome FROM Empregados WHERE Sobrenomes = 'King' SELECT Sobrenomes, Nome FROM Empregados WHERE Sobrenomes Like 'S*' SELECT Sobrenomes, Salario FROM Empregados WHERE Salario Between 200 And 300 SELECT Sobrenomes, Salario FROM Empregados WHERE Sobrenomes Between 'Lon' And 'Tol' Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
57
Manuais e recursos para desenvolvimento web www.criarweb.com
SELECT IdPedido, DataPedido FROM Pedidos WHERE DataPedido Between #01-01-1994# And #12-31-1994# SELECT Sobrenomes, Nome, Cidade FROM Empregados WHERE Cidade In ('Sevilha', 'Los Angeles', 'Barcelona')
Artigo por Claudio
Como exibir informações com múltiplas instruções SQL Ao utilizar múltiplas instruções SQL economizamos os recursos compartilhados da rede e servidor, como largura de banda, memória, CPU, pois reduzimos o número de acessos ao servidor web. Neste artigo, veremos como retornar registros com uma stored procedure com duas instruções SQL. Inicialmente, declaramos a string de conexão com o banco de dados string strConexao = "Data Source=(local);Integrated Security=SSPI;Initial Catalog=Northwind;";
e a stored procedure usada no exemplo: string sSql = "GetTotalAndProdutos";
Se preferir utilize instruções SQL separadas por ponto-e-vírgula: string sSql = " SELECT Count(*) AS Total FROM Products; SELECT ProductName, UnitPrice FROM Products";
Com a instrução using criamos uma nova instância da classe SqlConnection e passamos a string de conexão: using (SqlConnection conn = new SqlConnection(strConexao))
{
Criamos e definimos um objeto SqlDataReader como null. SqlDataReader r = null;
Em seguida, criamos uma nova instância da classe SqlCommand e passamos ao construtor o objeto SqlConnection e a string com o nome da stored procedure. SqlCommand cmd = new SqlCommand(sSql, conn);
Definimos a propriedade CommandType como StoredProcedure. cmd.CommandType = CommandType.StoredProcedure;
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
58
Manuais e recursos para desenvolvimento web www.criarweb.com
Ao usar instruções SQL defina a propriedade CommandType como Text: cmd.CommandType = CommandType.Text;
Dentro dos blocos try, catch, finally, respectivamente, abrimos e exibimos os dados, manipulamos as exceções que podem ocorrer e fechamos a conexão com o banco de dados. try { conn.Open();
Definimos o objeto SqlDataReader: r = cmd.ExecuteReader(CommandBehavior.CloseConnection);
Retornamos o índice do campo "total": int t = r.GetOrdinal("total");
Exibimos a string "Total de registros:". Response.Write("Total de registros: ");
Iniciamos a leitura dos dados r.Read();
e exibimos o total de registros retornados: Response.Write(r.GetInt32(t) + "
");
Usamos o método NextResult para exibir os registros do próximo conjunto de registros. r.NextResult();
Verificamos se há registros para exibir: if (r.HasRows)
Neste caso especifico, podemos usar também: if (r.GetInt32(t) > 0)
Em seguida, extraímos o índice do campo ProductName e do campo UnitPrice. int produto = r.GetOrdinal("ProductName"); int valor = r.GetOrdinal("UnitPrice");
Criamos a tabela onde exibiremos os dados. Response.Write("Produto | Valor unitário |
");
Percorremos todos os registros do segundo conjunto de registros. Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
59
Manuais e recursos para desenvolvimento web www.criarweb.com
while (r.Read()) {
Exibimos o nome do produto com o método GetString Response.Write("" + r.GetString(produto) + " | ");
e o valor unitário de cada produto com o método GetDecimal: Response.Write("" + string.Format(ci,"{0:c}", r.GetDecimal(valor)) + " |
");
O método Format da classe String formata a saída como um valor monetário string.Format(ci,"{0:c}", r.GetDecimal(valor))
e define a cultura como pt-BR - Português Brasil. Desta forma, a saída será sempre em reais, independente do idioma usado pelo computador do usuário. CultureInfo ci = new CultureInfo("pt-BR");
Ao finalizar o exemplo, exibimos a tag de fechamento da tabela Response.Write("
");
exibimos o bloco catch catch (SqlException) { Response.Write("Erro SQL."); }
e o bloco finally, onde encerramos a conexão com o banco de dados. finally { }
if (!r.IsClosed) r.Close();
A seguir, temos os arquivos e códigos que compõe este exemplo. //Arquivo de exemplo: Default.aspx.cs using System; using System.Web.UI; using System.Web.UI.WebControls; using System.Data; using System.Data.SqlClient; using System.Globalization; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { string strConexao = "Data Source=(local);Integrated Security=SSPI;Initial Catalog=Northwind;"; string sSql = "GetTotalAndProdutos";
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
60
Manuais e recursos para desenvolvimento web www.criarweb.com using (SqlConnection conn = new SqlConnection(strConexao)) { SqlDataReader r = null; SqlCommand cmd = new SqlCommand(sSql, conn); cmd.CommandType = CommandType.Text; try { conn.Open(); r = cmd.ExecuteReader(CommandBehavior.CloseConnection); int t = r.GetOrdinal("total"); Response.Write("Total de registros: "); r.Read(); Response.Write(r.GetInt32(t) + "
"); r.NextResult(); if (r.HasRows) { int produto = r.GetOrdinal("ProductName"); int valor = r.GetOrdinal("UnitPrice"); Response.Write("Produto | Valor unitário |
"); CultureInfo ci = new CultureInfo("pt-BR"); while (r.Read()) { Response.Write("" + r.GetString(produto) + " | "); Response.Write("" + string.Format(ci,"{0:c}", r.GetDecimal(valor)) + " |
"); } Response.Write("
"); } } catch (SqlException) { Response.Write("Erro SQL."); } finally { if (!r.IsClosed) r.Close(); } } } }
Temos o arquivo Default.aspx <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> Exemplo com o método NextResult
e a stored procedure GetTotalAndProdutos usada no exemplo: CREATE PROCEDURE GetTotalAndProdutos AS SET NOCOUNT ON Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
61
Manuais e recursos para desenvolvimento web www.criarweb.com SELECT Count(*) AS Total FROM Products SELECT ProductName, UnitPrice FROM Products GO Sobre o autor: Alfredo Lotar é consultor, programador, escritor. Desenvolve aplicações com ASP.NET, JavaScript, XML, C#, Visual Basic e SQL Server. É autor do livro XML para Programadores ASP, da editora Axcel Books, e dos livros ASP.NET com C# ? Curso Prático, e Como programar com ASP.NET e C#, ambos publicados pela Novatec Editora. Atualmente, passa a maior parte do tempo desenvolvendo aplicações, escrevendo livros ou artigos, testando códigos e analisando falhas de segurança em web sites de clientes. O autor pode ser contactado pelo e-mail: [email protected].
Artigo por Alfredo Lotar
Critérios de seleção em SQL II Combine os registros com valores idênticos, na lista de campos especificados, em um único registro. Para cada registro se cria um valor sumário se se inclui uma função SQL agregada, como por exemplo, Sum ou Count, na instrução SELECT. Sua sintaxe é: SELECT campos FROM tabela WHERE criterio GROUP BY campos do grupo
GROUP BY é opcional. Os valores de resumo se omitem se não existe uma função SQL agregada na instrução SELECT. Os valores Null nos campos GROUP BY se agrupam e não se omitem. Não obstante, os valores Null não se avaliam em nenhuma das funções SQL agregadas. Utiliza-se a cláusula WHERE para excluir aquelas filas que não deseja agrupar, e a cláusula HAVING para filtrar os registros uma vez agrupados. Ao menos que contenha um dado Memo ou Objeto OLE, um campo da lista de campos GROUP BY pode se referir a qualquer campo das tabelas que aparecem na cláusula FROM, inclusive se o campo não estiver incluído na instrução SELECT, sempre e quando a instrução SELECT incluir pelo menos uma função SQL agregada. Todos os campos da lista de campos de SELECT devem ou se incluir na cláusula GROUP BY, ou como argumentos de uma função SQL agregada. SELECT IdFamilia, Sum(Stock) AS StockAtual FROM Produtos GROUP BY IdFamilia
Uma vez que GROUP BY combinou os registros, HAVING mostra qualquer registro agrupado pela cláusula GROUP BY que satisfaça as condições da cláusula HAVING. HAVING é similar a WHERE, determina que registros se selecionam. Uma vez que os registros se agruparam utilizando GROUP BY, HAVING determina quais deles serão mostrados. SELECT IdFamilia, Sum(Stock) AS StockAtual FROM Produtos Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
62
Manuais e recursos para desenvolvimento web www.criarweb.com GROUP BY IdFamilia HAVING StockAtual > 100 AND NomeProduto Like BOS*
AVG Calcula a média aritmética de um conjunto de valores contidos em um campo especificado de uma consulta. Sua sintaxe é a seguinte: Avg(expr)
Onde expr representa o campo que contém os dados numéricos para os que se deseja calcular a média ou uma expressão que realiza um cálculo utilizando os dados de tal campo. A média calculada por Avg é a média aritmética (a soma dos valores dividido pelo número de valores). A função Avg não inclui nenhum campo Null no cálculo. SELECT Avg(Gastos) AS Promedio FROM Pedidos WHERE Gastos > 100
Count Calcula o número de registros devolvidos por uma consulta. Sua sintaxe é a seguinte Count(expr)
Onde expr contém o nome do campo que se deseja contar. Os operandos de expr podem incluir o nome de um campo de uma tabela, uma constante ou uma função (a qual pode ser intrínseca ou definida pelo usuário, mas não outras das funções agregadas de SQL). Pode contar com qualquer tipo de dados inclusive texto. Embora expr possa realizar um cálculo sobre um campo, Count simplesmente conta o número de registros sem ter em conta que valores se armazenam nos registros. A função Count não conta os registros que têm campos null a não ser que expr seja o caractere asterisco (*). Se utilizar um asterisco, Count calcula o número total de registros, incluindo aqueles que contém campos null. Count(*) é consideravelmente mais rápida que Count(Campo). Não se deve colocar o asterisco entre aspas duplas ('*'). SELECT Count(*) AS Total FROM Pedidos
Se expr identifica a múltiplos campos, a função Count conta um registro só se ao menos um dos campos não for Null. Se todos os campos especificados forem Null, não se contará o registro. Há que separar os nomes dos campos com ampersand (&). SELECT Count(DataEnvio & Transporte) AS Total FROM Pedidos Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
63
Manuais e recursos para desenvolvimento web www.criarweb.com
Podemos fazer com que o gestor conte os dados diferentes de um determinado campo SELECT Count(DISTINCT Localidade) AS Total FROM Pedidos
Max, Min Devolvem o mínimo ou o máximo de um conjunto de valores contidos em um campo especifico de uma consulta. Sua sintaxe é: Min(expr) Max(expr)
Onde expr é o campo sobre o qual se deseja realizar o cálculo. Expr pode incluir o nome de um campo de uma tabela, uma constante ou uma função (a qual pode ser intrínseca ou definida pelo usuário, porém não outras das funções agregadas de SQL). SELECT Min(Gastos) AS ElMin FROM Pedidos WHERE Pais = 'Espanha' SELECT Max(Gastos) AS ElMax FROM Pedidos WHERE Pais = 'Espanha'
StDev, StDevP Devolve estimações do desvio padrão para a povoação (o total dos registros da tabela) ou uma mostra da povoação representada (mostra aleatória). Sua sintaxe é: StDev(expr) StDevP(expr)
Onde expr representa o nome do campo que contém os dados que desejam avaliar ou uma expressão que realiza um cálculo utilizando os dados de tais campos. Os operandos de expr podem incluir o nome de um campo de uma tabela, uma constante ou uma função (a qual pode ser intrínseca ou definida pelo usuário, porém não outras das funções agregadas de SQL). StDevP avalia uma povoação, e StDev avalia uma mostra da povoação. Se a consulta contém menos de dois registros (ou nenhum registro para StDevP), estas funções devolvem um valor Null (o qual indica que o desvio padrão não pode se calcular). SELECT StDev(Gastos) AS Desvio FROM Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
64
Manuais e recursos para desenvolvimento web www.criarweb.com Pedidos WHERE País = 'Espanha' SELECT StDevP(Gastos) AS Desvio FROM Pedidos WHERE País = 'Espanha'
Sum Devolve a soma do conjunto de valores contido em um campo especifico de uma consulta. Sua sintaxe é: Sum(expr)
Onde expr representa o nome do campo que contém os dados que se desejam somar ou uma expressão que realiza um cálculo utilizando os dados de tais campos. Os operandos de expr podem incluir o nome de um campo de uma tabela, uma constante ou uma função (a qual pode ser intrínseca ou definida pelo usuário, mas não outras das funções agregadas de SQL). SELECT Sum(PrecoUnidade * Quantidad) AS Total FROM DetalhePedido
Var, VarP Devolve uma estimação da variabilidade de uma povoação (sobre o total dos registros) ou uma mostra da povoação (mostra aleatória de registros) sobre os valores de um campo. Sua sintaxe é: Var(expr) VarP(expr)
VarP avalia uma povoação, e Var avalia uma mostra da povoação. Expr o nome do campo que contém os dados que se desejam avaliar ou uma expressão que realiza um cálculo utilizando os dados de tais campos. Os operandos de expr podem incluir o nome de um campo de uma tabela, uma constante ou uma função (a qual pode ser intrínseca ou definida pelo usuário, mas não outras das funções agregadas de SQL) Se a consulta contiver menos de dois registros, Var e VarP devolvem Null (isto indica que a variabilidade não pode ser calculada). Pode utilizar Var e VarP em uma expressão de consulta ou em uma Instrução SQL. SELECT Var(Gastos) AS Variabilidade FROM Pedidos WHERE País = 'Espanha' SELECT VarP(Gastos) AS Variabilidade FROM Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
65
Manuais e recursos para desenvolvimento web www.criarweb.com Pedidos WHERE País = 'Espanha'
COMPUTE de SQL-SERVER Esta cláusula acrescenta uma fila no conjunto de dados que se está recuperando, se utiliza para realizar cálculos em campos numéricos. COMPUTE age sempre sobre um campo ou expressão do conjunto de resultados e esta expressão deve figurar exatamente igual na cláusula SELECT e sempre se deve ordenar o resultado pela mesma ou ao memos agrupar o resultado. Esta expressão não pode utilizar nenhum ALIAS. SELECT IdCliente, Count(IdPedido) FROM Pedidos GROUP BY IdPedido HAVING Count(IdPedido) > 20 COMPUTE Sum(Count(IdPedido)) SELECT IdPedido, (PrecoUnidade * Quantidade - Desconto) FROM [Detalhes de Pedidos] ORDER BY IdPedido COMPUTE Sum((PrecoUnidade * Quantidade - Desconto)) // Calcula o Total BY IdPedido // Calcula o Subtotal
Artigo por Claudio
Consultas de ação As consultas de ação são aquelas que não devolvem nenhum registro, são as encarregadas de ações como adicionar, excluir e modificar registros. Tanto as sentenças de atualização como as de exclusão desencadeiarão (segundo o motor de dados) as atualizações em cascata, exclusões em cascata, restrições e valores padrões definidos para os diferentes campos ou tabelas afetadas pela consulta. DELETE Cria uma consulta de eliminação que elimina os registros de uma ou mais das tabelas listadas na cláusula FROM que satisfaçam a cláusula WHERE. Esta consulta elimina os registros completos, não é possível eliminar o conteúdo de algum campo em concreto. Sua sintaxe é: DELETE FROM Tabela WHERE criterio Uma vez eliminados os registros utilizando uma consulta de exclusão, não se poderá desfazer a operação. Se desejar saber que registros foram eliminados, primeiro examine os resultados de uma consulta de seleção que utilize o mesmo critério e depois execute a consulta de exclusão. Mantenha cópias de segurança (back ups) de seus dados em todo momento. Se Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
66
Manuais e recursos para desenvolvimento web www.criarweb.com
eliminar os registros errados poderá recuperá-los a través das cópias de segurança. DELETE FROM Empregados WHERE Cargo = 'Vendedor' INSERT INTO Agrega um registro em uma tabela. É conhecida como uma consulta de dados adicionados. Esta consulta pode ser de dois tipos: Inserir um único registro ou Inserir em uma tabela os registros contidos em outra tabela. Para inserir um único Registro: Neste caso a sintaxe é a seguinte: INSERT INTO Tabela (campo1, campo2, ..., campoN) VALUES (valor1, valor2, ..., valorN) Esta consulta grana no campo1 o valor1, no campo2 e valor2 e assim, sucessivamente. Para selecionar registros e inseri-los em uma tabela nova Neste caso, a sintaxe é a seguinte: SELECT campo1, campo2, ..., campoN INTO novatabela FROM tabelaorigem [WHERE criterios] Pode-se utilizar as consultas de criação de tabela para arquivar registros, fazer cópias de segurança das tabelas ou fazer cópias para exportar a outro banco de dados ou utilizar em informes que mostrem os dados de um período de tempo concreto. Por exemplo, se poderia criar um informe de Vendas mensais por região executando a mesma consulta de criação de tabela a cada mês. Para inserir Registros de outra Tabela: Neste caso, a sintaxe é: INSERT INTO Tabela [IN base_externa] (campo1, campo2, , campoN) SELECT TabelaOrigem.campo1, TabelaOrigem.campo2,,TabelaOrigem.campoN FROM Tabela Origem Neste caso se selecionarão os campos 1,2,..., n da tabela origem e se gravarão nos campos 1,2,.., n da Tabela. A condição SELECT pode incluir a cláusula WHERE para filtrar os registros a copiar. Se Tabela e Tabela Origem possuem a mesma estrutura podemos simplificar a sintaxe a: INSERT INTO Tabela SELECT Tabela Origem.* FROM Tabela Origem Desta forma os campos de Tabela Origem se gravarão em Tabela, para realizar esta operação é Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
67
Manuais e recursos para desenvolvimento web www.criarweb.com
necessário que todos os campos de Tabela Origem estejam contidos com igual nome em Tabela. Com outras palavras que Tabela possua todos os campos de Tabela Origem (igual nome e igual tipo). Neste tipo de consulta há que ter especial atenção com os campos contadores ou autonuméricos visto que ao inserir um valor em um campo deste tipo se escreve o valor que contenha seu campo homólogo na tabela origem, não incrementando-se como lhe corresponde. Pode-se utilizar a instrução INSERT INTO para agregar um registro único a uma tabela, utilizando a sintaxe da consulta de adição de registro único tal e como se mostrou anteriormente. Nesse caso, seu código especifica o nome e o valor de cada campo do registro. Deve especificar cada um dos campos do registro ao que se vai atribuir um valor assim como o valor para tal campo. Quando não se especifica tal campo, se insere o valor pré-determinado ou Null. Os registros se agregam no final da tabela. Também se pode utilizar INSERT INTO para agregar um conjunto de registros pertencentes a outra tabela ou consulta utilizando a cláusula SELECT... FROM como se mostrou anteriormente na sintaxe da consulta de adição de múltiplos registros. Neste caso, a cláusula SELECT especifica os campos que se vão agregar na tabela destino especificada. A tabela destino ou origem pode especificar uma tabela ou uma consulta. Se a tabela destino contiver uma chave principal, há que certificar-se que é a única, e com valores não nulos; se não for assim, não se agregarão os registros. Se se agregam registros a uma tabela com um campo Contador, não se deve incluir o campo Contador na consulta. Pode-se empregar a cláusula IN para agregar registros a uma tabela em outro banco de dados. Pode-se averiguar os registros que se agregarão na consulta executando primeiro uma consulta de seleção que utilize o mesmo critério de seleção e ver o resultado. Uma consulta de adição copia os registros de uma ou mais tabelas em outra. As tabelas que contém os registros que se vão agregar não se verão afetadas pela consulta de adição. Ao invés de agregar registros existentes em outra tabela, pode-se especificar os valores de cada campo em um novo registro utilizando a cláusula VALUES. Se se omite a lista de campos, a cláusula VALUES deve incluir um valor para cada campo da tabela, de outra forma falhará INSERT. Exemplos INSERT INTO Clientes SELECT ClientesAntigos.* FROM ClientesNovos SELECT Empregados.* INTO Programadores FROM Empregados WHERE Categoria = 'Programador'
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
68
Manuais e recursos para desenvolvimento web www.criarweb.com
Esta consulta cria uma tabela nova chamada programadores com a mesma estrutura que a tabela empregado e copia aqueles registros cujo campo categoria seja programador INSERT INTO Empregados (Nome, Sobrenome, Cargo) VALUES ( 'Luis', 'Sánchez', 'Estagiario' ) INSERT INTO Empregados SELECT Vendedores.* FROM Vendedores WHERE Cidade = 'Madri' UPDATE Cria uma consulta de atualização que muda os valores dos campos de uma tabela especificada baseando-se em um critério específico. Sua sintaxe é: UPDATE Tabela SET Campo1=Valor1, Campo2=Valor2, CampoN=ValorN WHERE Criterio UPDATE é especialmente útil quando se deseja mudar um grande número de registros ou quando estes se encontram em múltiplas tabelas. Pode mudar vários campos de uma só vez. O exemplo seguinte incrementa os valores Quantidade pedidos em um 10 por cento e os valores Transporte em um 3 por cento para aqueles que se tiverem enviado ao Reino Unido.: UPDATE Pedidos SET Pedido = Pedidos * 1.1, Transporte = Transporte * 1.03 WHERE PaisEnvio = 'ES' UPDATE não gera nenhum resultado. Para saber que registros mudarão, há que examinar primeiro o resultado de uma consulta de seleção que utilize o mesmo critério e depois executar a consulta de atualização. UPDATE Empregados SET Grau = 5 WHERE Grau = 2 UPDATE Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
69
Manuais e recursos para desenvolvimento web www.criarweb.com
Produtos SET Preco = Preco * 1.1 WHERE Provedor = 8 AND Familia = 3 Se em uma consulta de atualização suprimimos a cláusula WHERE todos os registros da tabela assinalada serão atualizados. UPDATE Empregados SET Salario = Salario * 1.1 Artigo por Claudio
Tipos de dados SQL Os tipos de dados SQL se classificam em 13 tipos de dados primários e de vários sinônimos válidos reconhecidos por tais tipos de dados. Os tipos de dados primários são:
Tipo de Dados
Longitude
Descrição
BINARY
1 byte
Para consultas sobre tabela anexa de produtos de banco de dados que definem um tipo de dados Binário.
BIT
1 byte
Valores Sim/Não ou True/False
BYTE
1 byte
Um valor inteiro entre 0 e 255.
COUNTER
4 bytes
Um número incrementado automaticamente (de tipo Long)
CURRENCY
8 bytes
Um inteiro escalável entre 922.337.203.685.477,5808 e 922.337.203.685.477,5807.
DATETIME
8 bytes
Um valor de data ou hora entre os anos 100 e 9999.
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
70
Manuais e recursos para desenvolvimento web www.criarweb.com
4 bytes
Um valor em ponto flutuante de precisão simples com uma classificação de - 3.402823*1038 a -1.401298*10-45 para valores negativos, 1.401298*10- 45 a 3.402823*1038 para valores positivos, e 0.
DOUBLE
8 bytes
Um valor em ponto flutuante de dupla precisão com uma classificação de - 1.79769313486232*10308 a -4.94065645841247*10-324 para valores negativos, 4.94065645841247*10-324 a 1.79769313486232*10308 para valores positivos, e 0.
SHORT
2 bytes
Um inteiro curto entre -32,768 e 32,767.
LONG
4 bytes
Um inteiro longo entre -2,147,483,648 e 2,147,483,647.
LONGTEXT
1 byte por caractere
De zero a um máximo de 1.2 gigabytes.
SINGLE
LONGBINAR Segundo se Y necessite TEXT
1 byte por caractere
De zero 1 gigabyte. Utilizado para objetos OLE.
De zero a 255 caracteres.
A seguinte tabela recolhe os sinônimos dos tipos de dados definidos: Tipo de Dado
Sinônimos
BINARY
VARBINARY
BIT
BOOLEAN LOGICAL LOGICAL1 YESNO
BYTE
INTEGER1
COUNTER
AUTOINCREMENT
CURRENCY
MONEY
DATETIME
DATE TIME
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
71
Manuais e recursos para desenvolvimento web www.criarweb.com
TIMESTAMP
SINGLE
FLOAT4 IEEESINGLE REAL
DOUBLE
FLOAT FLOAT8 IEEEDOUBLE NUMBER NUMERIC
SHORT
INTEGER2 SMALLINT
LONG
INT INTEGER INTEGER4
LONGBINARY
GENERAL OLEOBJECT
LONGTEXT
LONGCHAR MEMO NOTE
TEXT
ALPHANUMERIC CHAR - CHARACTER STRING - VARCHAR
VARIANT (Não Admitido)
VALUE
Artigo por Claudio
Subconsultas em SQL Uma subconsulta é uma instrução SELECT adicionada dentro de uma instrução SELECT, SELECT...INTO, INSERT...INTO, DELETE, ou UPDATE ou dentro de outra subconsulta. Pode utilizar três formas de sintaxe para criar uma subconsulta: comparação [ANY | ALL | SOME] (instrução sql) sql)
expressão [NOT] IN (instrução sql)
[NOT] EXISTS (instrução
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
72
Manuais e recursos para desenvolvimento web www.criarweb.com
Onde: uma expressão e um operador de comparação que compara a expressão comparação É com o resultado da subconsulta. expressão
É uma expressão pela qual se busca o conjunto resultante da subconsulta.
instrução SQL
É uma instrução SELECT, que segue o mesmo formato e regras que qualquer outra SELECT. Deve ir entre parênteses.
Pode-se utilizar uma subconsulta no lugar de uma expressão na lista de campos de uma instrução SELECT ou em uma cláusula WHERE ou HAVING. Em uma subconsulta, se utiliza uma instrução SELECT para proporcionar um conjunto de um ou mais valores especificados para avaliar na expressão da cláusula WHERE ou HAVING. Pode-se utilizar o predicado ANY ou SOME, os quais são sinônimos, para recuperar registros da consulta principal, que satisfaçam a comparação com qualquer outro registro recuperado na subconsulta. O exemplo seguinte devolve todos os produtos cujo preço unitário for maior que o de qualquer produto vendido com um desconto igual ou maior ao 25 por cento: SELECT * FROM Produtos WHERE PrecoUnidade ANY ( SELECT PrecoUnidade FROM DetalhePedido WHERE Desconto = 0 .25 )
O predicado ALL se utiliza para recuperar unicamente aqueles registros da consulta principal que satisfazem a comparação com todos os registros recuperados na subconsulta. Se se muda ANY por ALL no exemplo anterior, a consulta devolverá unicamente aqueles produtos cujo preço unitário for maior que o de todos os produtos vendidos com um desconto igual ou maior ao 25 por cento. Isto é muito mais restritivo. O predicado IN se emprega para recuperar unicamente aqueles registros da consulta principal para os que alguns registros da subconsulta contém um valor igual. O exemplo seguinte devolve todos os produtos vendidos com um desconto igual ou maior ao 25 por cento: SELECT * FROM Produtos WHERE IDProduto IN ( SELECT IDProduto FROM DetalhePedido Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
73
Manuais e recursos para desenvolvimento web www.criarweb.com
)
WHERE Desconto = 0.25
Inversamente, pode-se utilizar NOT IN para recuperar unicamente aqueles registros da consulta principal para os que não têm nenhum registro da subconsulta que contenha um valor igual. O predicado EXISTS (com palavra reservada NOT opcional) se utiliza em comparações de verdade/falso para determinar se a subconsulta devolve algum registro. Suponhamos que desejamos recuperar todos aqueles clientes que tiverem realizado pelo menos um pedido: SELECT Clientes.Companhia, Clientes.Telefone FROM Clientes WHERE EXISTS ( SELECT FROM Pedidos WHERE Pedidos.IdPedido = Clientes.IdCliente )
Esta consulta é equivalente a esta outra: SELECT Clientes.Companhia, Clientes.Telefone FROM Clientes WHERE IdClientes IN ( SELECT Pedidos.IdCliente FROM Pedidos )
Pode-se utilizar também alias do nome da tabela em uma subconsulta para se referir às tabelas listadas na cláusula FROM fora da subconsulta. O exemplo seguinte devolve os nomes dos empregados cujo salário for igual ou maior do que o salário médio de todos os empregados com o mesmo título. À tabela Empregados foi dado o alias T1: SELECT Sobrenome, Nome, Titulo, Salario FROM Empregados AS T1 WHERE Salario = ( SELECT Avg(Salario) FROM Empregados WHERE T1.Titulo = Empregados.Titulo ) ORDER BY Titulo
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
74
Manuais e recursos para desenvolvimento web www.criarweb.com
No exemplo anterior, a palavra reservada AS é opcional. SELECT Sobrenomes, Nome, Cargo, Salario FROM Empregados WHERE Cargo LIKE 'Agente Ven*' AND Salario ALL ( SELECT Salario FROM Empregados WHERE Cargo LIKE '*Chefe*' OR Cargo LIKE '*Diretor*' )
(Obtém uma lista com o nome, cargo e salário de todos os agentes de ventas cujo salário for maior que o de todos os chefes e diretores.) SELECT DISTINCT NomeProduto, Preco_Unidade FROM Produtos WHERE PrecoUnidade = ( SELECT PrecoUnidade FROM Produtos WHERE NomeProduto = 'Almíbar anisado' )
(Obtém uma lista com o nome e o preço unitário de todos os produtos com o mesmo preço que o almíbar anisado.) SELECT DISTINCT NomeContato, NomeCompanhia, CargoContato, Telefone FROM Clientes WHERE IdCliente IN ( SELECT DISTINCT IdCliente FROM Pedidos WHERE DataPedido <#07/01/1993# )
(Obtém uma lista das companhias e dos contatos de todos os clientes que realizaram um pedido no segundo trimestre de 1993.) SELECT Nome, Sobrenomes FROM Empregados AS E WHERE EXISTS ( Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
75
Manuais e recursos para desenvolvimento web www.criarweb.com
)
SELECT * FROM Pedidos AS O WHERE O.IdEmpregado = E.IdEmpregado
(Seleciona o nome de todos os empregados que reservaram pelo menos um pedido.) SELECT DISTINCT Pedidos.Id_Produto, Pedidos.Quantidade, ( SELECT Produtos.Nome FROM Produtos WHERE Produtos.IdProduto = Pedidos.IdProduto ) AS ElProduto FROM Pedidos WHERE Pedidos.Quantidade = 150 ORDER BY Pedidos.Id_Produto
(Recupera o Código do Produto e a Quantidade pedida da tabela pedidos, extraindo o nome do produto da tabela de produtos.) SELECT NumVoo, Lugares FROM Voos WHERE Origem = 'Madri' AND Exists ( SELECT T1.NumVoo FROM Voos AS T1 WHERE T1.LuagaresLivres > 0 AND T1.NumVuelo=Vuelos.NumVuelo)
(Recupera números de vôo e capacidades de aqueles vôos com destino Madri e lugares livres Suponhamos agora que temos uma tabela com os identificadores de todos nossos produtos e o stock de cada um deles. Em outra tabela se encontram todos os pedidos que temos pendentes de servir. Trata-se de averiguar que produtos não se podem servir por falta de estoque. SELECT PedidosPendentes.Nome FROM PedidosPendentes GROUP BY PedidosPendentes.Nome HAVING SUM(PedidosPendentes.Quantidade < ( SELECT Produtos.Estoque FROM Produtos WHERE Produtos.IdProduto = PedidosPendentes.IdProduto ) )
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
76
Manuais e recursos para desenvolvimento web www.criarweb.com
Suponhamos que em nossa tabela de empregados desejamos buscar todas as mulheres cuja idade seja maior da de qualquer homem: SELECT Empregados.Nome FROM Empregados WHERE Sexo = 'M' AND Idade > ANY (SELECT Empregados.Idade FROM Empregados WHERE Sexo ='H') Ou o que seria o mesmo: SELECT Empregados.Nome FROM Empregados WHERE Sexo = 'M' AND Idade > (SELECT Max( Empregados.Idade )FROM Empregados WHERE Sexo ='H')
A seguinte tabela mostra algum exemplo do operador ANY e ALL Valor Operador Valor 2 Resultado 1 3
> ANY
(2,5,7)
Certo
3
= ANY
(2,5,7)
Falso
3
= ANY
(2,3,5,7) Certo
3
> ALL
(2,5,7)
Falso
3
< ALL
(5,6,7)
Falso
A operação =ANY é equivalente ao operador IN, ambos devolvem o mesmo resultado. Artigo por Claudio
Consultas SQL de União Internas Consultas de Combinação entre tabelas As vinculações entre tabelas se realizam mediante a cláusula INNER que combina registros de duas tabelas sempre que tiver concordância de valores em um campo comum. Sua sintaxe é: SELECT campos FROM tb1 INNER JOIN tb2 ON tb1.campo1 comp tb2.campo2
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
77
Manuais e recursos para desenvolvimento web www.criarweb.com
Onde: tb1, tb2
São os nomes das tabelas desde as que se combinam os registros.
campo1, campo2
São os nomes dos campos que se combinam. Se não são numéricos, os campos devem ser do mesmo tipo de dados e conter o mesmo tipo de dados, porém não tem que ter o mesmo nome.
comp
É qualquer operador de comparação relacional: =, <,<>, <=, =>, ó >.
Pode-se utilizar uma operação INNER JOIN em qualquer cláusula FROM. Isto cria uma combinação por equivalência, conhecida também como união interna. As combinações equivalentes são as mais comuns; estas combinam os registros de duas tabelas sempre que tiver concordância de valores em um campo comum a ambas tabelas. Pode-se utilizar INNER JOIN com as tabelas Departamentos e Empregados para selecionar todos os empregados de cada departamento. Do contrário, para selecionar todos os departamentos (inclusive se algum deles não tiver nenhum empregado atribuído) se emprega LEFT JOIN ou todos os empregados (inclusive se algum não estiver atribuído a nenhum departamento), neste caso RIGHT JOIN. Se se tenta combinar campos que contenham dados Memo ou Objeto OLE, se produz um erro. Podem-se combinar dois campos numéricos quaisquer, inclusive se são de diferentes tipos de dados. Por exemplo, pode combinar um campo Numérico para o que a propriedade Size de seu objeto Field está estabelecida como Inteiro, e um campo Contador. O exemplo seguinte mostra como poderia combinar as tabelas Categorias e Produtos baseando-se no campo IDCategoria: SELECT NomeCategoria, NomeProduto FROM Categorias INNER JOIN Produtos ON Categorias.IDCategoria = Produtos.IDCategoria
No exemplo anterior, IDCategoria é o campo combinado, porém não está incluído na saída da consulta já que não está incluído na instrução SELECT. Para incluir o campo combinado, incluir o nome do campo na instrução SELECT, neste caso, Categorias.IDCategoria. Também se pode linkar várias cláusulas ON em uma instrução JOIN, utilizando a seguinte sintaxe: SELECT campos FROM tabela1 INNER JOIN tabela2 ON (tb1.campo1 comp tb2.campo1 AND ON tb1.campo2 comp tb2.campo2) OR ON (tb1.campo3 comp tb2.campo3)
Também pode aninhar instruções JOIN utilizando a seguinte sintaxe: SELECT campos FROM tb1 INNER JOIN (tb2 INNER JOIN [( ]tb3 [INNER JOIN [( ]tablax [INNER JOIN ...)]
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
78
Manuais e recursos para desenvolvimento web www.criarweb.com ON tb3.campo3 comp tbx.campox)] ON tb2.campo2 comp tb3.campo3) ON tb1.campo1 comp tb2.campo2
Um LEFT JOIN ou um RIGHT JOIN pode se aninhar dentro de um INNER JOIN, porém um INNER JOIN não pode se aninhar dentro de um LEFT JOIN ou um RIGHT JOIN. Exemplo: SELECT DISTINCT Sum(PrecoUnitario * Quantidade) AS Sales, (Nome + ' ' + Sobrenome) AS Name FROM Empregados INNER JOIN( Pedidos INNER JOIN DetalhesPedidos ON Pedidos.IdPedido = DetalhesPedidos.IdPedido) ON Empregados.IdEmpregado = Pedidos.IdEmpregado GROUP BY Nome + ' ' + Sobrenome
(Cria duas combinações equivalentes: uma entre as tabelas Detalhes de pedidos e Pedidos, e a outra entre as tabelas Pedidos e Empregados. Isto é necessário já que a tabela Empregados não contem dados de vendas e a tabela Detalhes de pedidos não contem dados dos empregados. A consulta produz uma lista de empregados e suas vendas totais.) Se empregarmos a cláusula INNER na consulta se selecionarão só aqueles registros da tabela da que tivermos escrito à esquerda de INNER JOIN que contenham ao menos um registro da tabela que tivermos escrito à direita. Para solucionar isto temos duas cláusulas que substituem a palavra-chave INNER, estas cláusulas são LEFT e RIGHT. LEFT toma todos os registros da tabela da esquerda embora não tenha nenhum registro na tabela da esquerda. RIGHT realiza a mesma operação, porém ao contrário, toma todos os registros da tabela da direita embora não tenha nenhum registro na tabela da esquerda. A sintaxe exposta anteriormente pertence a ACCESS, onde todas as sentenças com a sintaxe funcionam corretamente. Os manuais de SQL-SERVER dizem que esta sintaxe é incorreta e que há que adicionar a palavra reservada OUTER: LEFT OUTER JOIN e RIGHT OUTER JOIN. Na prática funciona corretamente de uma forma ou de outra. Não obstante, os INNER JOIN ORACLE não é capaz de interpretá-los, mas existe uma sintaxe em formato ANSI para os INNER JOIN que funcionam em todos os sistemas. Tomando como referência a seguinte sentença: SELECT Faturas.*, Alvaras.* FROM Faturas INNER JOIN Alvaras ON Faturas.IdAlvara = Alvaras.IdAlvara WHERE Faturas.IdCliente = 325 Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
79
Manuais e recursos para desenvolvimento web www.criarweb.com
A transformação desta sentença a formato ANSI seria a seguinte: SELECT Faturas.*, Alvaras.* FROM Faturas, Alvaras WHERE Faturas.IdAlvara = Alvaras.IdAlvara AND Faturas.IdCliente = 325
Como se pode observar as mudanças realizadas foram as seguintes: 1. Todas as tabelas que intervêm na consulta se especificam na cláusula FROM. 2. As condições que vinculam às tabelas se especificam na cláusula WHERE e se vinculam mediante o operador lógico AND. Referente aos OUTER JOIN, não funcionam em ORACLE e ademais conheço uma sintaxe que funciona nos três sistemas. A sintaxe em ORACLE é igual à sentença anterior, porém adicionando os caracteres (+) atrás do nome da tabela na qual desejamos aceitar valores nulos, isto equivale a um LEFT JOIN: SELECT Faturas.*, Alvaras.* FROM Faturas, Alvaras WHERE Faturas.IdAlvara = Alvaras.IdAlvara (+) AND Faturas.IdCliente = 325
E isto a um RIGHT JOIN: SELECT Faturas.*, Alvaras.* FROM Faturas, Alvaras WHERE Faturas.IdAlvara (+) = Alvaras.IdAlvara AND Faturas.IdCliente = 325
Em SQL-SERVER se pode utilizar uma sintaxe parecida, neste caso não se utiliza os caracteres (+), e sim os caracteres =* para o LEFT JOIN e *= para o RIGHT JOIN. Consultas de Auto-combinação A auto-combinação se utiliza para unir uma tabela consigo mesma, comparando valores de duas colunas com o mesmo tipo de dados. A sintaxe na seguinte: SELECT alias1.coluna, alias2.coluna, ... FROM tabla1 as alias1, tabela2 as alias2 WHERE Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
80
Manuais e recursos para desenvolvimento web www.criarweb.com alias1.coluna = alias2.coluna AND outras condicoes
Por exemplo, para visualizar o número, nome e posto de cada empregado, junto com o número, nome e posto do supervisor de cada um deles se utilizaria a seguinte sentença: SELECT t.num_emp, t.nome, t.posto, t.num_sup,s.nome, s.posto FROM empregados AS t, empregados AS s WHERE t.num_sup = s.num_emp
Consultas de Combinações não Comuns A maioria das combinações está baseada na igualdade de valores das colunas que são o critério da combinação. As não comuns se baseiam em outros operadores de combinação, tais como NOT, BETWEEN, <>, etc. Por exemplo, para listar o grau salarial, nome, salário e posto de cada empregado ordenando o resultado por grau e salário haveria que executar a seguinte sentença: SELECT graus.grau,empregados.nome, empregados.salario, empregados.posto FROM empregados, graus WHERE empregados.salario BETWEEN grados.salarioinferior And grados.salariosuperior ORDER BY grados.grado, empregados.salario
Para listar o salário médio dentro de cada grau salarial haveria que lançar esta outra sentença: SELECT graus.grau, AVG(empregados.salario) FROM empregados, graus WHERE empregados.salario BETWEEN graus.salarioinferior And graus.salariosuperior GROUP BY graus.grau
CROSS JOIN (SQL-SERVER) Utiliza-se em SQL-SERVER para realizar consultas de união. Suponhamos que temos uma tabela com todos os autores e outra com todos os livros. Se desejássemos obter uma listagem combinando ambas tabelas de tal forma que cada autor aparecesse junto a cada título, utilizaríamos a seguinte sintaxe: SELECT Autores.Nome, Livros.Titulo FROM Autores CROSS JOIN Livros
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
81
Manuais e recursos para desenvolvimento web www.criarweb.com
SELF JOIN SELF JOIN é uma técnica empregada para conseguir o produto cartesiano de uma tabela consigo mesma. Sua utilização não é muito freqüente, mas colocaremos algum exemplo de sua utilização. Suponhamos a seguinte tabela (O campo autor é numérico, embora para ilustrar o exemplo utilize o nome): Autores Código (Código do livro)
Autor (Nome do Autor)
B0012
1. Francisco López
B0012
2. Javier Alonso
B0012
3. Marta Rebolledo
C0014
1. Francisco López
C0014
2. Javier Alonso
D0120
2. Javier Alonso
D0120
3. Marta Rebolledo
Queremos obter, para cada livro, pares de autores: SELECT A.Codigo, A.Autor, B.Autor FROM Autores A, Autores B WHERE A.Codigo = B.Codigo
O resultado é o seguinte: Códig Autor o
Autor
B001 1. Francisco López 1. Francisco López 2 B001 1. Francisco López 2. Javier Alonso Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
82
Manuais e recursos para desenvolvimento web www.criarweb.com
2 B001 1. Francisco López 3. Marta Rebolledo 2 B001 2. Javier Alonso 2
2. Javier Alonso
B001 2. Javier Alonso 2
1. Francisco López
B001 2. Javier Alonso 2
3. Marta Rebolledo
B001 3. Marta Rebolledo 3. Marta Rebolledo 2 B001 3. Marta Rebolledo 2. Javier Alonso 2 B001 3. Marta Rebolledo 1. Francisco López 2 C001 1. Francisco López 1. Francisco López 4 C001 1. Francisco López 2. Javier Alonso 4 C001 2. Javier Alonso 4
2. Javier Alonso
C001 2. Javier Alonso 4
1. Francisco López
D012 2. Javier Alonso 0
2. Javier Alonso
D012 2. Javier Alonso 0
3. Marta Rebolledo
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
83
Manuais e recursos para desenvolvimento web www.criarweb.com
D012 3. Marta Rebolledo 3. Marta Rebolledo 0 D012 3. Marta Rebolledo 2. Javier Alonso 0 Como podemos observar, os pares de autores se repetem em cada um dos livros, podemos omitir estas repetições da seguinte forma: SELECT A.Codigo, A.Autor, B.Autor FROM Autores A, Autores B WHERE A.Codigo = B.Codigo AND A.Autor < B.Autor
O resultado agora é o seguinte: Códig Autor o
Autor
B0012 1. Francisco López 2. Javier Alonso B0012 1. Francisco López 3. Marta Rebolledo C0014 1. Francisco López 2. Javier Alonso D0120 2. Javier Alonso
3. Marta Rebolledo
Agora temos um conjunto de resultados em formato Autor - CoAutor. Se na tabela de empregados quiséssemos extrair todos os possíveis pares que podemos realizar, utilizaríamos a seguinte sentença: SELECT Homens.Nome, Mulheres.Nome FROM Empregados Homem, Empregados Mulheres WHERE Homem.Sexo = 'Homem' AND Mulheres.Sexo = 'Mulher' AND Homens.Id <>Mulheres.Id
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
84
Manuais e recursos para desenvolvimento web www.criarweb.com
Para concluir suponhamos a seguinte tabela: Empregados I d Nome
SeuChefe
1 Marcos 6 2 Lucas
1
3 Ana
2
4 Eva
1
5 Juan
6
6 Antonio Queremos obter um conjunto de resultados com o nome do empregado e o nome de seu chefe: SELECT Empre.Nome, Chefes.Nome FROM Empregados Empre, Empregados Chefe WHERE Empre.SeuChefe = Chefes.Id
Artigo por Claudio
Estruturas das tabelas em SQL Na terminologia usada em SQL não se menciona às relações, do mesmo modo que não se usa o termo atributo, porém sim a palavra coluna e linha. Criação de Tabelas Novas CREATE TABLE tabela ( campo1 tipo (tamanho) índice1, campo2 tipo (tamanho) índice2,... , índice multicampo , ... )
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
85
Manuais e recursos para desenvolvimento web www.criarweb.com
Onde: tabla
É o nome da tabela que será criada.
campo1 campo2
É o nome do campo ou dos campos que serão criados na nova tabela. A nova tabela deve conter, ao menos, um campo.
tipo
É o tipo de dados de campo na nova tabela.
tamanho
É o tamanho do campo, só se aplica para campos de tipo texto.
índice1 índice2
É uma cláusula CONSTRAINT que define o tipo de índice a criar. Esta cláusula é opcional.
índice É uma cláusula CONSTRAINT que define o tipo de índice multicampos a criar. multicamp Um índice multicampo é aquele que está indexado pelo conteúdo de vários os campos. Esta cláusula é opcional. CREATE TABLE Empregados ( Nome TEXT (25), Sobrenomes TEXT (50) )
(Cria uma nova tabela chamada Empregados com dois campos, um chamado Nome de tipo texto e longitud 25 e outro chamado sobrenomes com longitude 50). CREATE TABLE Empregados ( Nome TEXT (10), Sobrenomes TEXT, DataNascimento DATETIME ) CONSTRAINT IndiceGeral UNIQUE ( Nome, Sobrenomes, DataNascimento )
(Cria uma nova tabela chamada Empregados com um campo Nome de tipo texto e longitude 10, outro chamado Sobrenomes de tipo texto e longitude pré-determinada (50) e um mais chamado DataNascimento de tipo Data/Hora. Também cria um índice único - não permite valores repetidos - formado pelos três campos.) CREATE TABLE Empregados ( IdEmpregado INTEGER CONSTRAINT IndicePrimario PRIMARY, Nome TEXT, Sobrenomes TEXT, DataNascimento DATETIME )
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
86
Manuais e recursos para desenvolvimento web www.criarweb.com
(Cria uma tabela chamada Empregados com um campo Texto de longitude pré-determinada (50) chamado Nome e outro igual chamado Sobrenomes, cria outro campo chamado DataNascimento de tipo Data/Hora e o campo IdEmpregado de tipo inteiro o que estabelece como chave principal.) A cláusula CONSTRAINT Utiliza-se a cláusula CONSTRAINT nas instruções ALTER TABLE e CREATE TABLE para criar ou eliminar índices. Existem duas sintaxes para esta cláusula dependendo se deseja Criar ou Eliminar um índice de um único campo ou se se trata de um campo multi-índice. Se se utiliza o motor de dados de Microsoft, só poderá utilizar esta cláusula com os bancos de dados próprias de tal motor. Para os índices de campos únicos: CONSTRAINT nome {PRIMARY KEY | UNIQUE | REFERENCES tabela externa [(campo externo1, campo externo2)]}
Para os índices de campos múltiplos: CONSTRAINT nome {PRIMARY KEY (primario1[, primario2 [,...]]) | UNIQUE (único1[, único2 [, ...]]) | FOREIGN KEY (ref1[, ref2 [,...]]) REFERENCES tabela externa [(campo externo1 ,campo externo2 [,...])]} Onde: nome
É o nome do índice que se criará.
primarioN É o nome do campo ou dos campos que formam o índice primário. únicoN
É o nome do campo ou dos campos que formam o índice de chave única.
refN
É o nome do campo ou dos campos que formam o índice externo (fazem referência a campos de outra tabela).
tabela externa
É o nome da tabela que contém o campo ou os campos referenciados em refN
campos externos
É o nome do campo ou dos campos da tabela externa especificados por ref1, ref2,... , refN
Se se deseja criar um índice para um campo quando se está utilizando as instruções ALTER TABLE ou CREATE TABLE a cláusula CONTRAINT deve aparecer imediatamente depois da especificação do campo indexado.
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
87
Manuais e recursos para desenvolvimento web www.criarweb.com
Se se deseja criar um índice com múltiples campos quando se está utilizando as instruções ALTER TABLE ou CREATE TABLE a cláusula CONSTRAINT deve aparecer fora da cláusula de criação de tabela. Indic Descrição e UNIQ Gera um índice de chave única. O que implica que os registros da tabela não podem UE conter o mesmo valor nos campos indexados. PRIM Gera um índice primário o campo ou os campos especificados. Todos os campos da ARY chave principal devem ser únicos e não nulos, cada tabela só pode conter uma única KEY chave principal. Gera um índice externo (toma como valor do índice campos contidos em outras tabelas). Se a chave principal da tabela externa consta de mais de um campo, se deve utilizar uma definição de índice de múltiplos campos, listando todos os campos FORE de referência, o nome da tabela externa, e os nomes dos campos referenciados na IGN tabela externa na mesma ordem que os campos de referência listados. Se os KEY campos referenciados são a chave principal da tabela externa, não tem que especificar os campos referenciados, pré-determinado por valor, o motor Jet se comporta como se a chave principal da tabela externa estivesse formada pelos campos referenciados. Criação de Índices Se se utiliza o motor de dados Jet de Microsoft só se podem criar índices em banco ed dados do mesmo motor. A sintaxe para criar um índice em uma tabela já definida na seguinte: CREATE [ UNIQUE ] INDEX índice ON Tabela (campo [ASC|DESC][, campo [ASC|DESC], ...]) [WITH { PRIMARY | DISALLOW NULL | IGNORE NULL }]
Onde: índice
É o nome do índice a criar.
tabla
É o nome de uma tabela existente na que se criará o índice.
campo
É o nome do campo ou lista de campos que constituem o índice.
ASC| DESC
Indica a ordem dos valores dos campos ASC indica uma ordem ascendente (valor pré-determinado) e DESC uma ordem descendente.
UNIQUE Indica que o índice não pode conter valores duplicados.
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
88
Manuais e recursos para desenvolvimento web www.criarweb.com
DISALL OW Proíbe valores nulos no índice NULL IGNORE Exclui do índice os valores nulos incluídos nos campos que o compõem. NULL ao índice a categoria de chave principal, em cada tabela só pode existir PRIMAR Atribui um único índice que seja "Chave Principal". Se um índice é chave principal implica Y que não pode conter valores nulos nem duplicados. No caso de ACCESS, se pode utilizar CREATE INDEX para criar um pseudo índice sobre uma tabela adjunta em uma fonte de dados ODBC tal como SQL Server que não tenha ainda um índice. Não necessita permissão ou ter acesso a um servidor remoto para criar um pseudo índice, ademais o banco de dados remoto não é consciente e não é afetado pelo pseudo índice. Utiliza-se a mesma sintaxe para as tabelas adjuntas que para as originais. Isto é especialmente útil para criar um índice em uma tabela que seria só de leitura devido à falta de um índice. CREATE INDEX MeuIndice ON Empregados (Prefixo, Telefone) (Cria um índice chamado MeuIndice na tabela empregados com os campos Prefixo e Telefone.) CREATE UNIQUE INDEX MeuIndice ON Empregados (IdEmpregado) WITH DISALLOW NULL
(Cria um índice na tabela Empregados utilizando o campo IdEmpregado, obrigando que o campo IdEmpregado não contenha valores nulos nem repetidos.) Modificar o Desenho de uma Tabela Modifica o desenho de uma tabela já existente, se podem modificar os campos ou os índices existentes. Sua sintaxe é: ALTER TABLE tabela {ADD {COLUMN tipo de campo[(tamanho)] [CONSTRAINT índice] CONSTRAINT índice multicampo} | DROP {COLUMN campo I CONSTRAINT nome do índice}}
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
89
Manuais e recursos para desenvolvimento web www.criarweb.com
Onde: tabla
É o nome da tabela que se deseja modificar.
campo
É o nome do campo que se adicionará ou eliminará.
tipo
É o tipo de campo que adicionará.
tamanho
É o tamanho do campo que se adicionará (só para campos de texto).
índice
É o nome do índice do campo (quando se criam campos) ou o nome do índice da tabela que se deseja eliminar.
índice multicamp É o nome do índice do campo multicampo (quando se criam campos) ou o nome do índice da tabela que se deseja eliminar. o
Operaç Descrição ão ADD Utiliza-se para adicionar um novo campo à tabela, indicando o nome, o tipo de COLU campo e opcionalmente o tamanho (para campos de tipo texto). MN ADD
Utiliza-se para agregar um índice de multicampos ou de um único campo.
DROP COLU Utiliza-se para apagar um campo. Especifica-se unicamente o nome do campo. MN DROP Utiliza-se para eliminar um índice. Especifica-se unicamente o nome do índice a seguir da palavra reservada CONSTRAINT. ALTER TABLE Empregados ADD COLUMN Salario CURRENCY (Agrega um campo Salario de tipo Moeda a tabela Empregados.) ALTER TABLE Empregados DROP COLUMN Salario (Elimina o campo Salario da tabela Empregados.)
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
90
Manuais e recursos para desenvolvimento web www.criarweb.com ALTER TABLE Pedidos ADD CONSTRAINT RelacaoPedidos FOREIGN KEY (IdEmpregado) REFERENCES Empregados (IdEmpregado) (Agrega um índice externo à tabela Pedidos. O índice externo se baseia no campo IdEmpregado e se refere ao campo IdEmpregado da tabela Empregados. Neste exemplo, não é necessário indicar o campo junto ao nome da tabela na cláusula REFERENCES, pois ID_Empregado é a chave principal da tabela Empregados.) ALTER TABLE Pedidos DROP CONSTRAINT RelacaoPedidos (Elimina o índice da tabela Pedidos.)
Artigo por Claudio
Cursores em SQL Em alguns SGDB é possível a abertura de cursores de dados desde o próprio ambiente de trabalho, para isso se utilizam, normalmente procedimentos armazenados. A sintaxe para definir um cursor é a seguinte: DECLARE nome-cursor FOR especificacao-consulta [ORDER BY] Por exemplo: DECLARE Meu_Cursor FOR SELECT num_emp, nome, posto, salario FROM empregados WHERE num_dept = 'informatica' Este comando é meramente declarativo, simplesmente especifica as filas e colunas que iremos recuperar. A consulta se executa quando se abre ou se ativa o cursor. A cláusula [ORDER BY] é opcional e especifica uma ordenação para as filas do cursor; se não se especifica, a ordenação das filas é definida pelo gerenciador de SGBD. Para abrir ou ativar um cursor se utiliza o comando OPEN do SQL, a sintaxe é a seguinte: OPEN nome-cursor [USING lista-variaveis] Ao abrir o cursor, avalia-se a consulta que aparece em sua definição, utilizando os valores Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
91
Manuais e recursos para desenvolvimento web www.criarweb.com
atuais de qualquer parâmetro referenciado na consulta, para produzir uma coleção de filas. O ponteiro se posiciona diante da primeira fila de dados (registro atual), esta sentença não recupera nenhuma fila. Uma vez aberto o cursor, utiliza-se a cláusula FETCH para recuperar as filas do cursor, a sintaxe é a seguinte: FETCH nome-cursor INTO lista-variaveis Lista - variaveis são as variáveis que vão conter os dados recuperados da fila do cursor, na definição devem ir separadas por vírgulas. Na lista de variáveis, deve-se definir tantas variáveis como colunas quantas tiver a fila a recuperar. Para fechar um cursor, utiliza-se o comando CLOSE, este comando faz desaparecer o ponteiro sobre o registro atual. A sintaxe é: CLOSE nome-cursor Por último, e para eliminar o cursor, utiliza-se o comando DROP CURSOR. Sua sintaxe é a seguinte: DROP CURSOR nome-cursor Exemplo (sobre SQL-SERVER): Abrir um cursor e percorrê-lo DECLARE Employee_Cursor CURSOR FOR SELECT LastName, FirstName FROM Northwind.dbo.Employees WHERE LastName like 'B%' OPEN Employee_Cursor FETCH NEXT FROM Employee_Cursor WHILE @@FETCH_STATUS = 0 BEGIN FETCH NEXT FROM Employee_Cursor END CLOSE Employee_Cursor DEALLOCATE Employee_Cursor Abrir um cursor e imprimir seu conteúdo SET NOCOUNT ON Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
92
Manuais e recursos para desenvolvimento web www.criarweb.com
DECLARE @au_id varchar(11), @au_fname varchar(20), @au_lname varchar(40), @message varchar(80), @title varchar(80) PRINT "-------- Utah Authors report --------" DECLARE authors_cursor CURSOR FOR SELECT au_id, au_fname, au_lname FROM authors WHERE state = "UT" ORDER BY au_id OPEN authors_cursor FETCH NEXT FROM authors_cursor INTO @au_id, @au_fname, @au_lname WHILE @@FETCH_STATUS = 0 BEGIN PRINT " " SELECT @message = "----- Books by Author: " + @au_fname + " " + @au_lname PRINT @message DECLARE titles_cursor CURSOR FOR SELECT t.title FROM titleauthor ta, titles t WHERE ta.title_id = t.title_id AND ta.au_id = au_id OPEN titles_cursor FETCH NEXT FROM titles_cursor INTO @title IF @@FETCH_STATUS <> 0 PRINT " <>" WHILE @@FETCH_STATUS = 0 BEGIN
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
93
Manuais e recursos para desenvolvimento web www.criarweb.com
SELECT @message = " " + @title PRINT @message FETCH NEXT FROM titles_cursor INTO @title END CLOSE titles_cursor DEALLOCATE titles_cursor FETCH NEXT FROM authors_cursor INTO @au_id, @au_fname, @au_lname END CLOSE authors_cursor DEALLOCATE authors_cursor GO Percorrer um cursor USE pubs GO DECLARE authors_cursor CURSOR FOR SELECT au_lname FROM authors WHERE au_lname LIKE "B%" ORDER BY au_lname OPEN authors_cursor FETCH NEXT FROM authors_cursor WHILE @@FETCH_STATUS = 0 BEGIN FETCH NEXT FROM authors_cursor END CLOSE authors_cursor DEALLOCATE authors_cursor Percorrer um cursor salvando os valores em variáveis USE pubs GO DECLARE @au_lname varchar(40) DECLARE @au_fname varchar(20) DECLARE authors_cursor CURSOR FOR SELECTau_lname, au_fname FROM authors WHERE au_lname LIKE "B%" Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
94
Manuais e recursos para desenvolvimento web www.criarweb.com
ORDER BY au_lname, au_fname OPEN authors_cursor FETCH NEXT FROM authors_cursor INTO @au_lname, @au_fname WHILE @@FETCH_STATUS = 0 BEGIN PRINT "Author: " + @au_fname + " " + @au_lname FETCH NEXT FROM authors_cursor INTO @au_lname, @au_fname END CLOSE authors_cursor DEALLOCATE authors_cursor Artigo por Claudio
Referências Cruzadas em SQL Uma consulta de referências cruzadas é aquela que nos permite visualizar os dados em filas e em colunas, estilo tabela, por exemplo: Produto / Ano
1996 1997
Calças
1.250 3.000
Camisas
8.560 1.253
Sapatos
4.369 2.563
Se tivermos uma tabela de produtos e outra tabela de pedidos, podemos visualizar em total de produtos pedidos por ano para um artigo determinado, tal e como se visualiza na tabela anterior. A sintaxe para este tipo de consulta é a seguinte: TRANSFORM função agregada instrução select PIVOT campo pivot [IN (valor1[, valor2[, ...]])]
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
95
Manuais e recursos para desenvolvimento web www.criarweb.com
Onde: função agregada
É uma função SQL agregada que opera sobre os dados selecionados.
instrução select
É uma instrução SELECT.
campo pivot
É o campo ou expressão que deseja utilizar para criar os cabeçalhos da coluna no resultado da consulta.
valor1, valor2 São valores fixos utilizados para criar os cabeçalhos da coluna. Para resumir dados utilizando uma consulta de referência cruzada, se selecionam os valores dos campos ou expressões especificadas como cabeçalhos de colunas de tal forma que podem se ver os dados em um formato mais compacto que com uma consulta de seleção. TRANSFORM é opcional, porém se for incluída é a primeira instrução de uma cadeia SQL. Precede à instrução SELECT que especifica os campos utilizados como cabeçalhos de fila e uma cláusula GROUP BY que especifica o agrupamento das filas. Opcionalmente pode incluir outras cláusulas como, por exemplo, WHERE, que especifica uma seleção adicional ou um critério de ordenação. Os valores devolvidos em campo pivot se utilizam como cabeçalhos de coluna no resultado da consulta. Por exemplo, ao utilizar as cifras de vendas no mês da venda como pivot em uma consulta de referência cruzada se criariam 12 colunas. Pode restringir o campo pivot para criar cabeçalhos a partir dos valores fixos (valor1, valor2) listados na cláusula opcional IN. Também pode incluir valores fixos, para os que não existem dados, para criar colunas adicionais. Exemplos TRANSFORM Sum(Quantidade) AS Vendas SELECT Produto, Quantidade FROM Pedidos WHERE Data Between #01-01-1998# And #12-31-1998# GROUP BY Produto ORDER BY Produto PIVOT DatePart("m", Data) (Cria uma consulta de tabela de referências cruzadas que mostra as vendas de produtos por mês para um ano específico. Os meses aparecem da esquerda à direita como colunas e os nomes dos produtos aparecem de cima para baixo como filas.) TRANSFORM Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
96
Manuais e recursos para desenvolvimento web www.criarweb.com Sum(Quantidade) AS Vendas SELECT Companhia FROM Pedidos WHERE Data Between #01-01-1998# And #12-31-1998# GROUP BY Companhia ORDER BY Companhia PIVOT "Trimestre " & DatePart("q", Data) In ('Trimestre1', 'Trimestre2', 'Trimestre 3', 'Trimestre 4') (Cria uma consulta de tabela de referências cruzadas que mostra as vendas de produtos por trimestre de cada provedor no ano indicado. Os trimestres aparecem da e squerda à direta como colunas e os nomes dos provedores aparecem de cima para baixo como filas.)
Um caso prático: Trata-se de resolver o seguinte problema: temos uma tabela de produtos com dois campos, o código e o nome do produto. Temos outra tabela de pedidos na que anotamos o código do produto, a data do pedido e a quantidade pedida. Desejamos consultar os totais de produto por ano, calculando a média anual de vendas. Estrutura e dados das tabelas:
Para resolver a consulta sondaremos a seguinte consulta: TRANSFORM Sum(Pedidos.Quantidade) AS Resultado SELECT Nombre AS Produto, Pedidos.Id AS Código, Sum(Pedidos.Quantidade) AS TOTAL, Avg(Pedidos.Quantidade) AS Media FROM Pedidos, Artigos WHERE Pedidos.Id = Artigos.Id GROUP BY Pedidos.Id, Artigos.Nome PIVOT Year(Data) Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
97
Manuais e recursos para desenvolvimento web www.criarweb.com
E obtemos o seguinte resultado: Produt Código Total Media 1996 1997 o Sapato 1 s
348
87
Calças 2
955
238,75 375
Blusas 3
1940 485
300
620
48 580 1320
Comentários à consulta: A cláusula TRANSFORM indica o valor que desejamos visualizar nas colunas que realmente pertencem à consulta, neste caso 1996 e 1997, visto que ademais colunas são opcionais. SELECT especifica o nome das colunas opcionais que desejamos visualizar, neste caso, Produto, Código, Total e Média, indicando o nome do campo que desejamos mostrar em cada coluna ou o valor da mesma. Se incluirmos uma função de cálculo o resultado se fará baseando-se nos dados da fila atual e não ao total dos dados. FROM especifica a origem dos dados. A primeira tabela que deve figurar é aquela de onde desejamos extrair os dados, esta tabela deve conter ao menos três campos, um para os títulos da fila, outros para os títulos da coluna e outro para calcular o valor das células. Neste caso em concreto se desejava visualizar o nome do produto, como na tabela de pedidos só figurava o código do mesmo se adicionou uma nova coluna na cláusula select chamada Produto que se corresponda com o campo Nome da tabela de artigos. Para vincular o código do artigo da tabela de pedidos com o nome do mesmo da tabela artigos, foi inserido a cláusula INNER JOIN. A cláusula GROUP BY especifica o agrupamento dos registros, contrariamente aos manuais de instrução esta cláusula não é opcional já que deve figurar sempre e devemos agrupar os registros pelo campo do qual extrairemos a informação. Neste caso existem dois campos dos que extraímos a informação: pedidos.quantidade e artigos.nome, por isso, agrupamos pelos campos. Para finalizar, a cláusula PIVOT indica o nome das colunas não opcionais, neste caso 1996 e 1997 e como vamos ao dado que aparecerá nas colunas, neste caso empregamos o ano em que se produziu o pedido, extraindo-o do campo pedidos.fecha. Outras possibilidades de data da cláusula pivot são as seguintes: 1. Para agrupamento por Trimestres: PIVOT "Tri " & DatePart("q",[Data]); 2. Para agrupamento por meses (sem ter em conta o ano) PIVOT Format([Data],"mmm") In ("Jan", "Fev", "Mar", "Abr", "Maio", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"); 3. Para agrupar por dias Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
98
Manuais e recursos para desenvolvimento web www.criarweb.com
PIVOT Format([Data],"Short Date"); Artigo por Claudio
Introdução a freetext e contains em SQL-Server FULL TEXT SEARCH Utiliza-se em campos de texto de grande tamanho utilizando uns índices denominados catálogos. Estes catálogos só se podem utilizar com tabelas que contenham que definidas chaves primárias e armazenam todas as palavras do conteúdo das tabelas com execeção dos artigos, preposições, etc. Os catálogos não se atualizam automaticamente nem se salvam junto com o banco de dados e cada tabela pode ter um único catálogo. Para a utilização destes catálogos dentro de uma consulta, podemos utilizar dois métodos, o primeiro consiste em incluir os critérios dentro de uma cláusula WHERE (CONTAINS ou FREETEXT) e o segundo é utilizando uma tabela temporária que contém o ratio de acerto na consulta (CONTAINSTABLE ou FREETEXTTABLE). O predicado CONTAINS Utiliza-se este predicado para buscar um texto específico em uma tabela. Seu funcionamento é similar ao predicado LIKE, a diferença é que este não pode realizar buscas nos campos grandes de texto. CONTAINS não diferencia entre maiúsculas e minúsculas. Sintaxe: SELECT FROM WHERE CONTAINS(,) OR/AND CONTAINS(,)
O predicado CONTAINS suporta sintaxe complexas para buscar: • • • •
Uma ou mais palavras utilizando os operadores lógicos AND/OR. Famílias de palavras Uma palavra ou uma frase que comecem por um determinado texto. Palavras ou frases que estejam umas próximas de outras.
Para buscar uma palavra em um campo: SELECT title_id, title, notes FROM titles WHERE CONTAINS(notes,'business')
Para localizar uma frase em um campo: SELECT title_id, titles, notes FROM titles WHERE CONTAINS(notes,' "common business applications" ')
Para localizar uma frase em todos os campos habilitados:
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
99
Manuais e recursos para desenvolvimento web www.criarweb.com SELECT title_id, titles, notes FROM titles WHERE CONTAINS(*, ' "common business applications" ')
Utilizando AND, OR e NOT SELECT title, notes FROM titles WHERE CONTAINS(notes, ' "favorite recipes" OR "gourmet recipes" ') SELECT titles, notes FROM titles WHERE CONTAINS(notes, ' cooking AND NOT ("computer*") ') SELECT titles, notes FROM titles WHERE CONTAINS(notes, ' beer AND ales ') SELECT titles, notes FROM titles WHERE CONTAINS(*, '("ice skating" OR hockey) AND NOT olympics')
Utilizando caracteres curingas SELECT titles, notes FROM titles WHERE CONTAINS(notes,' "ice*" ') SELECT titles, notes FROM titles WHERE CONTAINS(notes, ' "light bread*" ')
Busca de palavras ou frases indicando a importância das palavras: Esta busca permite indicar o peso que terá cada uma das palavras ou frases que se buscam sobre o resultado da busca, o peso oscila entre o valor mais baixo 0.0 e o valor mais alto 1.0. SELECT Cliente, Nome, Endereco FROM Cliente WHERE CONTAINS (Endereco, 'ISABOUT ( "Rua*", Velazquez WEIGHT(0.5), Serrano(0.9)')
(Serão encontrados todos aqueles registros que no campo endereço exista a cadeia rua seguida de qualquer valor, ordenando primeiro os de "Rua Serrano", logo os de "Rua Velázquez" e depois o resto. Busca de palavras próximas: Podemos realizar buscas por duas palavras e indicar que se encontrem próximas uma da outra. A ordem das palavras não altera o resultado da busca. SELECT titulo, notas FROM livros WHERE CONTAINS (notas, "usuario NEAR computador") SELECT titulo, notas FROM livros WHERE CONTAINS (notas, "usuario ~ computador")
Podem-se indicar três palavras, de tal forma que a segunda e a primeira devem estar próximas ao igual que a segunda e a terceira. SELECT titulo, notas FROM livros WHERE CONTAINS (notas, "usuario ~ principiante ~ computador")
Buscas com frases: ... WHERE CONTAINS(Descricao, " salsas ~ "mezcl*" ") ... WHERE CONTAINS(Descricao, " "carne*" ~ "salsa empanada*" ")
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
100
Manuais e recursos para desenvolvimento web www.criarweb.com
O predicado FREETEXT Ao utilizar este predicado se analisam todas as palavras das frases e nos devolve como resultado, aqueles registros que contém a frase completa ou algum fragmento da mesma. A sintaxe é igual que o predicado CONTAINS. ... FREETEXT(descricao, ' "Em um lugar da mancha de cujo nome não quero me lembrar" ')
O predicado CONTAINSTABLE Este predicado tem igual funcionamento e sintaxe que CONTAINS a diferença que neste caso devolve uma tabela com duas colunas, a primeira chamada [KEY] contem o valor da chave primária da tabela que a que buscamos, a segunda chamada RANK devolve um valor indicando a porcentagem de acerto na busca para cada registro. SELECT Perguntas.Pergunta, Perguntas.Resposta, Resultado.RANK FROM Perguntas, CONTAINSTABLE(Resposta, " SQL Server") AS Resultado WHERE Perguntas.IdPergunta = Resultado.[KEY] ORDER BY Resultado.RANK Desc SELECT Perguntas.Pergunta, Perguntas.Resposta, Resultado.RANK FROM Perguntas INNER JOIN CONTAINSTABLE (Resposta, "SQL Server") AS Resultado ON Perguntas.IdPergunta = Resultados.KEY
O predicado FREETEXTTABLE É o equivalente a CONTAINSTABLE porém realizando buscas de FREETEXT. Artigo por Claudio
Acesso ao banco de dados externos Para o acesso a banco de dados externos se utiliza a cláusula IN. Pode-se acessar a banco de dados dBase, Paradox ou Btrieve. Esta cláusula só permite a conexão de um banco de dados externa por vez. Um banco de dados externo é um banco de dados que não seja o ativo. Embora para melhorar os rendimentos é melhor anexá-los ao banco de dados atual e trabalhar com eles. Para especificar um banco de dados que não pertence a Access Basic, se agrega um ponto e vírgula (;) ao nome e se fecha entre aspas simples. Também pode utilizar a palavra reservada DATABASE para especificar o banco de dados externo. Por exemplo, as linhas seguintes especificam a mesma tabela: FROM Tabela IN '[dBASE IV; DATABASE=C: \DBANCO\DADOS\VENDAS;]'; FROM Tabla IN 'C: \DBANCO\DADOS\VENDAS' 'dBASE IV;'
Acesso a um banco de dados externo de Microsoft Access: SELECT IdCliente FROM Clientes Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
101
Manuais e recursos para desenvolvimento web www.criarweb.com IN 'C:\MEUSDADOS.MDB' WHERE IDCliente Like 'A*'
(Onde MEUSDADOS.MDB é o nome de um banco e dados de Microsoft Access que contém a tabela Clientes.) Acesso a um banco de dados externo de dBASE III ou IV: SELECT IdCliente FROM Clientes IN 'C:\DBANCO\DADOS\VENDAS' 'dBASE IV'; WHERE IDCliente Like 'A*'
(Para recuperar dados de uma tabela de dBASE III+ há que utilizar 'dBASE III+;' em lugar de 'dBASE IV;'.) Acesso a um banco de dados de Paradox 3.x o 4.x: SELECT IdCliente FROM Clientes IN 'C:\PARADOX\DADOS\VENDAS' 'Paradox 4.x;' WHERE IDCliente Like 'A*'
(Para recuperar dados de uma tabela de Paradox versão 3.x, há que substituir 'Paradox 4.x;' por 'Paradox 3.x;'.) Acesso a um banco de dados de Btrieve: SELECT IdCliente FROM Clientes IN 'C:\BTRIEVE\DADOS\VENDAS\FILE.DDF' 'Btrieve;' WHERE IDCliente Like 'A*'
(C:\BTRIEVE\DADOS\VENDAS\FILE.DDF é a rota de acesso e nome de arquivo do arquivo de definição de dados de Btrieve.) Artigo por Claudio
Consultas com parâmetros e omissão de permissões Consultas com parâmetros As consultas com parâmetros são aquelas cujas condições de busca se definem mediante parâmetros. Se se executam diretamente desde o banco de dados onde foram definidas aparecerá uma mensagem solicitando o valor de cada um dos parâmetros. Se desejarmos Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
102
Manuais e recursos para desenvolvimento web www.criarweb.com
executá-las desde uma aplicação há que atribuir primeiro o valor dos parâmetros e depois executá-las. Sua sintaxe é a seguinte: PARAMETERS nome1 tipo1, nome2 tipo2, ... , nomeN tipoN Consulta Onde: nome
É o nome do parâmetro
tipo
É o tipo de dados do parâmetro
consult Uma consulta SQL a Podem-se utilizar nomes, mas não tipos de dados em uma cláusula WHERE ou HAVING. PARAMETERS PrecoMinimo Currency, DataInicio DateTime; SELECT IdPedido, Quantidade FROM Pedidos WHERE Preco = PrecoMinimo AND DataPedido = DataInicio
Omitir as permissões de acesso Em ambientes de bancos de dados com permissões de segurança para grupos de trabalho se pode utilizar a cláusula WITH OWNERACCESS OPTION para que o usuário atual adquira os direitos de proprietário na hora de executar a consulta. Sua sintaxe é: instrução sql WITH OWNERACCESS OPTION SELECT Sobrenome, Nome, Salario FROM Empregados ORDER BY Sobrenome WITH OWNERACCESS OPTION
Esta opção requer que esteja declarado o acesso ao arquivo de grupo de trabalho (geralmente system.mda ou system .mdw) do banco de dados atual. Artigo por Claudio
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
103
Manuais e recursos para desenvolvimento web www.criarweb.com
Procedures e busca de registros duplicados em SQL Cláusula Procedure Esta cláusula é pouco usual e se utiliza para criar uma consulta ao mesmo tempo que se executa, opcionalmente define os parâmetros da mesma. Sua sintaxe é a seguinte: PROCEDURE NomeConsulta ParÂmetro1 tipo1, .... , ParâmetroN tipon ConsultaSQL
Onde: NomeConsult É o nome com o qual se salvará a consulta no banco de dados. a Parâmetro
É o nome de parâmetro ou dos parâmetros de tal consulta.
Tipo
É o tipo de dados do parâmetro
ConsultaSQL É a consulta que se deseja gravar e executar. PROCEDURE ListaCategorias; SELECT DISTINCTROW NomeCategoria, IdCategoria FROM Categorias ORDER BY NomeCategoria (Atribui o nome Lista_de_categorias à consulta e a executa.) PROCEDURE Resumo DataInicio DATETIME, DtaaFinal DATETIME; SELECT DISTINCTROW DataEnvio, IdPedido, ImportePedido, Format(DataEnvio, "yyyy") AS Ano FROM Pedidos WHERE DataEnvio Between DataInicio And DataFinal (Atribui o nome Resumo à consulta e inclui dois parâmetros.)
Busca de Registros Duplicados Para gerar este tipo de consultas o mais simples é utilizar o assistente de consultas de Access, editar a sentença SQL da consulta e colá-la em nosso código. Não obstante, este tipo de consulta se consegue da seguinte forma: SELECT DISTINCT Lista de Campos a Visualizar FROM Tabela WHERE CampoDeBusca In (SELECT CampoDeBusca FROM Tabela As pseudônimo GROUP BY CampoDeBusca HAVING Count(*) > 1 ) ORDER BY CampoDeBusca
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
104
Manuais e recursos para desenvolvimento web www.criarweb.com
Um caso prático, se desejarmos localizar aqueles empregados com nome igual e visualizar seu código correspondente, a consulta seria a seguinte: SELECT DISTINCT Empregados.Nome, Empregados.IdEmpregado FROM Empregados WHERE Empregados.Nome In ( SELECT Nome FROM Empregados As Tmp GROUP BY Nome HAVING Count(*) > 1) ORDER BY Empregados.Nome
Artigo por Claudio
A função datepart() em Access Há alguns dias tinha que fazer uma consulta sobre datas em Access: "Obter o nome das empresas cuja data de inscrição coincidia com "x" ano" e li um artigo publicado em uma web com o título: "Funções para buscas com datas em Access". Depois de ler este artigo soube da existência da função DatePart(), porém a forma de colocá-la em prática tal como o problema me enfocava, não é nada simples, ou nesse momento, não o vi claro. De fato, fazendo uma busca, tudo era bastante confuso implementando programinhas em VBA (Visual Basic Aplications). (Importante: O formato de data em Access é o formato americano: mm/dd/aaaa, porém neste caso o formato americano e o da tabela quanto ao ano que se referem coincidem.)
Se realizamos a seguinte consulta: SELECT DatePart("yyyy",FECHA_ALTA) FROM table1;
Obtemos:
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
105
Manuais e recursos para desenvolvimento web www.criarweb.com
Até tudo bem, o problema surge quando você quer obter só um tipo de data na qual o ano coincida com um dado. Por exemplo, quero obter todas as empresas inscritas no ano 2003 e você dispõe de 1000 empresas com 1000 datas de inscrição... Para isso, há que fazer o seguinte: SELECT * FROM Tabela1 WHERE DatePart("yyyy",FECHA_ALTA)="2003";
Artigo por Jonathan Soriano Folch
Emular um Cursor SQL com um Loop Graças a este truque de SQL Server 2000 você poderá emular o funcionamento de um cursor com um loop. Para isso criaremos uma tabela temporária onde colocaremos os elementos que queremos iterar no loop para poder tratá-los. DECLARE @Anuncios TABLE ( pk_id numeric(18, 0) NOT NULL IDENTITY (1, 1), Idtruco numeric(18,0), IdUsuario numeric(18,0), Alias nvarchar(255), usuario nvarchar(255) ) Criamos duas variáveis para poder iterar no loop DECLARE @Rows numeric, @i numeric(18,0) SET @Rows=0 Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
106
Manuais e recursos para desenvolvimento web www.criarweb.com SET @i=1 Inserimos os dados na tabela temporária @anuncios INSERT INTO @Anuncios ( Idtruque, IdUsuario, Alias, Usuario ) SELECT a.ARTID, a.ARTUSR, p.Alias, p.LonUsr FROM TABELA_ANUNCIOS a INNER JOIN TABELA_USUARIOS p ON a.ARTUSR=p.LONID Atribuímos à variável contadora de filas totais o total da tabela @anuncios Set @Rows=(SELECT TOP 1 PK_ID FROM @Anuncios order BY PK_ID DESC) Iteramos com o while. Desta maneira podemos emular o funcionamento de um cursor sem ser um cursor, podendo executá-lo as vezes que quisermos de uma só vez. WHILE @i <;= @Rows BEGIN Declare @Idtruco numeric(18,0), @IdUsuario numeric(18,0), @Alias nvarchar(255), @Usuario nvarchar(255) SELECT @Idtruque=Idtruque, @IdUsuario=IdUsuario, @Alias=Alias, @Usuario=Usuario FROM @Anuncios WHERE pk_id=@i Realizar todas as ações! SET @i=@i + 1 END
Artigo por Pol Salvat
Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
107
Manuais e recursos para desenvolvimento web www.criarweb.com
Tipos de instruções SQL e seus componentes sintáticos Em SQL temos bastantes instruções que se podem utilizar para realizar diversas tarefas. Dependendo das tarefas, estas sentenças se podem classificar em três grupos principais (DML, DDL,DCL), embora nos restaria outro grupo que ao meu entender não está dentro da linguagem SQL, e sim da PLSQL. DML INSTRUÇÃO
DESCRIÇÃO Manipulação de dados SELECT INSERT DELETE UPDATE
Recupera dados do banco de dados. Adiciona novas filas de dados ao banco de dados. Suprime filas de dados do banco de dados. Modifica dados existentes no banco de dados. DDL Definição de dados CREATE TABLE DROP TABLE ALTER TABLE CREATE VIEW DROP VIEW CREATE INDEX DROP INDEX CREATE SYNOYM DROP SYNONYM
Adiciona uma nova tabela ao banco de dados. Suprime uma tabela do banco de dados. Modifica a estrutura de uma tabela existente. Adiciona uma nova vista ao banco de dados. Suprime uma vista do banco de dados. Constrói um índice para uma coluna. Suprime o índice para uma coluna. Define um alias para um nome de tabela. Suprime um alias para um nome de tabela. DCL Controle de acesso GRANT REVOKE Controle de transações COMMIT ROLLBACK
Concede privilégios de acesso a usuários. Suprime privilégios de acesso a usuários Manual Tutorial de SQL: http://www.criarweb.com/sql/ © Os manuais de CriarWeb.com têm copyright dos autores. Não reproduzir sem autorização.
108