SQL Tutorial Part II
Abstrato:
[A segunda parte do tutorial revisa v�rios aspectos b�sicos da linguagem SQL...]
Introdu��o
Esta � a segunda parte do curso de SQL, nesta parte vamos nos centrar nos
civersos comandos SQL, desde a cria��o da tabela, sua modifica��o e/ou dele��o.
Nos centraremos, sobretudo, no comando SELECT, que �, a meu modo de ver, o mais
importante de todos.
Espero que esta segunda parte seja amena e instrutiva.
Cria��o de uma tabela
Como vimos na primeira parte, para criar uma tabela, usamos o comando
CREATE com o qualificativo TABLE, com efeito, o comando CREATE serve para criar:
- - usuario : CREATE USER
- - tabelas : CREATE TABLE
- - indices : CREATE INDEX
- - visualizar : CREATE VIEW
O comando create indica ao gerenciador que temos alguma coisa a criar, logo
mostraremos aqui e como.
O que nos interessa no momento � a cria��o de uma tabela:
Syntaxe
CREATE TABLE nome ( coluna tipo [DEFAULT valor] [NOT NULL], ...
[INHERITS (herda, ...)]
[CONSTRAINT nom_cons CHECK (prova), CHECK (prova)] );
Onde :
Nome |
� o nome que se d� � tabela e como ser� referenciada por qualquer comando. |
Coluna |
� o nome como vamos conhecer esta coluna. |
Tipo |
� o tipo de dado (varchar, char, int, date, time, timestamp), postgres
temos outros tipos de dados, mas n�o s�o compat�veis com SQL Ansi. |
Valor |
O valor que ter� por default. |
Herda |
Este � o pr�prio Postgres, define uma heran�a de outra tabela, isto �,
criar� uma entidade que cont�m as colunas da tabela que estamos criando e
as heran�as. |
Nom_cons |
Isto define uma regra de integridade a respeitar cada vez que modificamos uma tabela. |
Prova |
Condi��o a comprovar. |
Exemplo :
CREATE TABLE paises (
cod_pais integer NOT NULL,
nome varchar(30))
CONSTRAINT cod_raro CHECK (cod_pais > 0 AND cod_pais < 154);
Com este exemplo criamos uma tabela de pa�ses, cada vez que inserimos um novo dado,
cumpriremos estas condi��es :
- - o c�digo do pa�s n�o ser� NULO, se tentarmos por um c�digo NULO, o gerenciador
nos retornar� uma mensagem de erro :
ExecAppend: Fail to add null value in not null attribute cod_pais
-
- - o c�digo do pais ser� superior a 0 ou inferior a 154, se tentarmos inserir
um c�digo do pais diferente, o gerenciador nos retornar� com uma mensagem de erro :
ExecAppend: rejected due to CHECK constraint cod_raro
Nota
O que quer dizer NULO? Em SQL existe dois estados, dados ou N�O dados, com efeito
podemos nos interessar por um campo que n�o tenha dados, tanto o zero (0), como o
espa�o s�o dados. SQL introduz o conceito de NULO e trabalha com NIL, um exemplo
pr�tico :
Tenho uma tabela com registro de faturas, com os seguintes campos:
cliente, importe, data_emision, data_pago
Quando crio a tabela, inserirei os dados:
cliente, importe, data_emision
Deixarei a data_pago em branco, desta forma poderei conhecer todas as faturas
n�o pagas com o seguinte comando :
SELECT * FROM facturas WHERE data_pago IS NULL;
Algu�m pode alegar que um zero (0) no campo data_pago, faria o mesmo papel,
� verdade, salvo que zero (0), n�o � uma data e me impede de criar data_pago
do tipo data e poder aplicar-lhe as fun��es pr�prias de datas.
Exemplos de cria��o com NULOS :
insert into paises values (15, NULL);
ou :
insert into paises (cod_pais) values (27);
a ausencia do campo (nome) implica que este receber� o valor NULO.
Modifica��o de uma tabela
No PostgreSQL a modifica��o s� sera completa com o acrescimo de nova(s) coluna(s).
ALTER TABLE tabela ADD nome tipo;
Onde :
Tabela |
Nome da tabela a modificar |
Nome |
Nome da coluna a acrescentar |
Tipo |
Tipo de dados (ver CREATE TABLE) |
Inser��o de dados numa tabela
Agora vamos inserir dados na nossa tabela :
SINTAXE :
INSERT INTO tabela [(coluna, coluna, ...)] VALUES (valor-1, valor-2, ...)
ou :
INSERT INTO tabela [(coluna, coluna, ...)] SELECT ....
Como vimos existe duas maneiras de inserirmos dados numa tabela, seja linha a linha
ou o resultado de uma sub-sele��o que pode devolver uma ou v�rias tabelas.
Quando inserimos linhas em uma tabela, SEMPRE poremos dados em todas as colunas
inclusive nas que mencionamos, estas foram criadas com valores NULOS.
Se no comando n�o especificamos que colunas vamos preencher, entendemos que
vamos por dados em todas, exemplo :
INSERT INTO paises VALUES (34, 'Espaqa');
Isto estaria errado :
INSERT INTO paises VALUES (34);
Mas, isto sim, estaria correto:
INSERT INTO paises (cod_pais) VALUES (34);
eu recomendo que em comandos embutidos em programas em C ou em fun��es do
banco de dados SEMPRE especifiquemos as colunas que vamos trabalhar, e se
acrescentamos uma nova coluna na tabela (ALTER TABLE), o pr�ximo INSERT, acusar�
um erro, Exemplo :
INSERT INTO paises VALUES (34, 'Espaqa');
INSERT 18301 1
ALTER TABLE paises add poblacion integer
INSERT INTO paises VALUES (34, 'Espaqa');
Isto daria um erro, j� que falta o dado para popula��o.
Nota
PostgreSQL, n�o gera erro, cria a linha com o campo (popula��o) NULO, e
isto � s� uma particularidade do PostgreSQL, qualquer outro gerenciador SQL
acusar� um erro.
Logo, nos sobra o outro tipo de INSERT, o que utiliza uma sub-sele��o.
Este tipo de insert realiza, muito frequentemente, para criar tabelas temporais
ou tabelas para realizar uma tarefa muito concreta de calculos especulativos.
A parte substituida � a que toca os dados, eles vem dados por uma instru��o
SELECT que se realizava previamente com a inser��o dos dados. A instru��o SELECT pode
devolver uma ou v�rias tabelas, esta instru��o SELECT tem as mesmas restri��es
que a pr�pria SELECT.
Sele��o de dados
Era aqui que eu queria chegar! :-))
Temos topado com a fortaleza dos comandos SQL, a linguagem SQL sem SELECT seria
como as lentilhas sem chori�o (olha que pus dificuldades para os tradutores :-)
O comando SELECT nos permite acessar aos dados, mas com a ressalva que pode
realizar buscas, uni�o de tabelas, fun��es sobre os dados ou sobre as regras de
busca (predicado)
Um exemplo :
select * from paises;
Outro exemplo :
SELECT a.nombre, SUM(popula��o)
FROM paises a, provincias b, municipios c
WHERE b.cod_pais = a.cod_pais
AND (c.cod_pais = b.cod_pais
AND c.cod_provincia = b.cod_provincia)
AND popula��o IS NOT NULL
GROUP BY a.nombre
ORDER BY sum ASC;
Eu explico, ped� a popula��o de todos os pa�ses em ordem por popula��o
em modo ascendente, simples.! N�O ! 8-O
Bem, para isso, acrescentei uma nova coluna (popula��o) a tabela municipios.
Isto fica assim :
create table municipios (cod_pais int,
cod_provincia int,
cod_municipio int,
nombre_municipio varchar(60),
popula��o int);
insert into municipios values (1, 1, 1, 'Pais 1, Provincia 1, Municipio 1', 5435);
insert into municipios values (2, 1, 1, 'Pais 2, Provincia 1, Municipio 1', 7832);
insert into municipios values (3, 1, 1, 'Pais 3, Provincia 1, Municipio 1', 4129);
insert into municipios values (1, 2, 1, 'Pais 1, Provincia 2, Municipio 1', 76529);
insert into municipios values (2, 2, 1, 'Pais 2, Provincia 2, Municipio 1', 9782);
insert into municipios values (3, 2, 1, 'Pais 3, Provincia 2, Municipio 1', 852);
insert into municipios values (1, 3, 1, 'Pais 1, Provincia 3, Municipio 1', 3433);
insert into municipios values (2, 3, 1, 'Pais 2, Provincia 3, Municipio 1', 7622);
insert into municipios values (3, 3, 1, 'Pais 3, Provincia 3, Municipio 1', 2798);
insert into municipios values (1, 1, 2, 'Pais 1, Provincia 1, Municipio 2', 7789);
insert into municipios values (2, 1, 2, 'Pais 2, Provincia 1, Municipio 2', 76511);
insert into municipios values (3, 1, 2, 'Pais 3, Provincia 1, Municipio 2', 98);
insert into municipios values (1, 2, 2, 'Pais 1, Provincia 2, Municipio 2', 123865);
insert into municipios values (2, 2, 2, 'Pais 2, Provincia 2, Municipio 2', 886633);
insert into municipios values (3, 2, 2, 'Pais 3, Provincia 2, Municipio 2', 982345);
insert into municipios values (1, 3, 2, 'Pais 1, Provincia 3, Municipio 2', 22344);
insert into municipios values (2, 3, 2, 'Pais 2, Provincia 3, Municipio 2', 179);
insert into municipios values (3, 3, 2, 'Pais 3, Provincia 3, Municipio 2', 196813);
insert into municipios values (1, 1, 3, 'Pais 1, Provincia 1, Municipio 3', 491301);
insert into municipios values (2, 1, 3, 'Pais 2, Provincia 1, Municipio 3', 166540);
insert into municipios values (3, 1, 3, 'Pais 3, Provincia 1, Municipio 3', 165132);
insert into municipios values (1, 2, 3, 'Pais 1, Provincia 2, Municipio 3', 0640);
insert into municipios values (2, 2, 3, 'Pais 2, Provincia 2, Municipio 3', 65120);
insert into municipios values (3, 2, 3, 'Pais 3, Provincia 2, Municipio 3', 1651462);
insert into municipios values (1, 3, 3, 'Pais 1, Provincia 3, Municipio 3', 60650);
insert into municipios values (2, 3, 3, 'Pais 2, Provincia 3, Municipio 3', 651986);
insert into municipios values (3, 3, 3, 'Pais 3, Provincia 3, Municipio 3', NULL);
commit work;
Eu sei que poder�amos fazer por ALTER TABLE, mas deveria usar o UPDATE e ainda n�o
os expliquei, assim se quiserem usem "cut & paste" e felicidades :-))
Agora vamos executar a pesquisa (QUERY), e o resultado deveria ser :
nome| sum
------+-------
pais 1| 705559
pais 2|1212418
pais 3|2804018
(3 rows)
Agora verificamos :
select sum(popula��o) from municipios where cod_pais = 1;
Resultado :
sum
------
791986
(1 row)
!!!!!! UMA DIFEREN�A !!!!!!!!!!
Olhemos a tabela das provincias, falta a provincia 3, fa�amos :
INSERT INTO PROVINCIAS VALUES (3, 1, 'Provincia 3, Pais 1');
INSERT INTO PROVINCIAS VALUES (3, 2, 'Provincia 3, Pais 2');
INSERT INTO PROVINCIAS VALUES (3, 3, 'Provincia 3, Pais 3');
E repetimos o comando, resultado :
nome| sum
------+-------
pais 1| 791986
pais 2|1872205
pais 3|3003629
Nos faltava a provincia 3 de cada pais.
Agora para os que tenham se perdido, lembremo-nos que as conjun��es entre
tabelas eram EXATAS, quer dizer, somente extrai dados se a condi��o dentro do
predicado � exato.
Olhemos a primeira parte do WHERE : b.cod_pais = a.cod_pais
Isto quer dizer que junto da tabela paises at� provincia sempre que o c�digo
do pa�s seja igual, agora recordemos os dados dos pa�ses que inserimos :
N�o o execute, � s� ilustra��o.
create table paises (cod_pais integer, nome varchar(30));
insert into paises values (1, 'pais 1');
insert into paises values (2, 'pais 2');
insert into paises values (3, 'pais 3');
commit work;
Agora os dados das provinvias :
create table provincias (cod_provincia int,
cod_pais int,
nom_provincia varchar(30));
insert into provincias values (1, 1, 'Provincia 1, Pais 1');
insert into provincias values (2, 1, 'Provincia 2, Pais 1');
insert into provincias values (1, 2, 'Provincia 1, Pais 2');
insert into provincias values (2, 2, 'Provincia 2, Pais 2');
insert into provincias values (1, 3, 'Provincia 1, Pais 3');
insert into provincias values (2, 3, 'Provincia 2, Pais 3');
commit work;
Faltam todas as provincias 3 de cada pa�s, mas na tabela de munic�pio est�o
todos os dados das provinvias com c�digo 3, assim que � normal que n�o some-se os dados
dos munic�pios das prov�ncias com c�digo 3, pode ser descartada a segunda
parte do where :
AND (c.cod_pais = b.cod_pais
AND c.cod_provincia = b.cod_provincia)
A provincia existia na tabela dos municipios mas N�O na tabela das provincias.
Para os que n�o entenderam, tome uma aspirina, ou v� passear com o cachorro (se
n�o tem cachorro v� passear sem cachorro), respirar um pouco de ar puro e volte
a come�ar desde a primeira parte.
� muito importante comprender como realizamos as conjun��es de dados, sem ele, os
desenvolvimentos que fizemos podem ter resultados imprevisiveis.
Fechemos os parenteses e comecemos com a sintaxe do comando SELECT.
SELECT [DISTINCT] expresion1 [AS nom-atributo] {, expresion-i [as nom-atributo-i]}
[INTO TABLE classname]
[FROM from-list]
[WHERE where-clause]
[GROUP BY attr_name1 {, attr_name-i....}]
[ORDER BY attr_name1 [ASC | DESC ] [USING op1 ] {, nom-atributo-i...}]
[UNION {ALL} SELECT ...]
Passo a passo :
DISTINCT : |
isto � para eliminar tabelas duplicadas na sa�da. |
expresion1 : |
queremos na sa�da, normalmente uma coluna de uma tabela da lista FROM. |
AS nom-atributo : |
um alias para o nome da coluna, exemplo:
manu=> select cod_pais from paises;
cod_pais
--------
1
2
3
(3 rows)
Agora con o alias :
manu=> select cod_pais as pasi from paises;
pasi
----
1
2
3
(3 rows)
|
INTO TABLE : |
permite inserir as tabelas resultantes diretamente em outra tabela .
(ver INSERT ... SELECT...) |
FROM : |
lista das tabelas na entrada |
WHERE : |
predicado da sele��o (crit�rios de uni�o e sele��o). |
GROUP BY : |
Crit�rio de agrupamento, certas fun��es que usamos na (expresion) podemos
precisar de um agrupamento, quer dizer, um crit�rio de discrimina��o e resultado.
|
ORDER BY : |
Criterio de ordena��o das tabelas de sa�das. ASC ordem ascendente, DESC ordem
descendente, USING define se a ordem da coluna n�o est� na lista (express�o...) |
UNION ALL SELECT : |
Isto define se acrescento al resultado do primeiro SELECT ao segundo
SELECT que pode ser de tabelas distintas, mas devolvendo o mesmo n�mero de colunas. |
Vimos que os comandos SELECT n�o s� devolvem os dados do BD, sim que tamb�m pode
modific�-los :
SELECT SUM(saldo * 1.1) - SUM(saldo) AS incremento FROM empregados;
Nos mostra o incremento de 10% a pagar no saldo.
Vamos ver quais as fun��es que temos a nossa disposi��o :
COUNT() : |
mostra a quantidade de tabelas n�o NULAS |
SUM() : |
mostra a soma total de uma coluna num�rica. |
AVG() : |
mostra o pre�o medio de uma coluna num�rica. |
MIN() : |
mostra o valor m�nimo de uma coluna |
MAX() : |
mostra o valor m�ximo de uma coluna |
FLOAT(int) : |
mostra um FLOAT8, FLOAT(12345) |
FLOAT4(int) : |
mostra um FLOAT4, FLOAT4(12345) |
INT(float) : |
mostra um INT de um FLOAT/4, INT(123.456) |
LOWER(texto) : |
mostra um texto em min�sculas. |
UPPER(texto) : |
mostra texto em mai�sculas. |
LPAD(texto, long, char) : |
preenche a esquerda com "char" no comprimeiro "long"
da coluna "texto" |
RPAD(texto, long, char) : |
preenche a direita com "char" no comprimento "long" da coluna "texto" |
LTRIM(texto, char) : |
apaga a esquerda de "texto" todo caractere "char" |
RTRIM(texto, char) : |
apaga a direita de "texto" todo caractere "char" |
POSITION(cadeia IN texto) : |
extrai do "texto" a posi��o da "cadeia", mas N�O FUNCIONA |
SUBSTR(texto,desde[,at�]) : |
extrai a sub-cadeia de "texto", da primeira posi�ao "de
sde" at� a posi��o "at�" o final da cadeia |
DATETIME(data, hora) : |
converte o formato datetime em data (AAAA-MM-DD) em hora (HH:MM) |
Estas s�o algumas fun��es em SQL, s�o as que est�o definidas em SQL ANSI
e est�o presentes no Postgres95.
Detalhes do where
At� agora vimos que na sess�o WHERE do SELECT coloc�vamos coisas como :
AND coluna = valor
Isto � uma pequena mostra do que podemos por ou combinar :
AND, OR, NOT, IN, IN ALL, =, !=, >, <, (SELECT....), LIKE lembrando que os
parenteses tem relevancia, exemplos :
WHERE
coluna IN (SELECT DISTINCT coluna FROM tabela WHERE ....)
coluna IN ('valor1','valor2','valor3',...)
(coluna = 'valor' and coluna = 'outro_valor' OR coluna != 'valor')
!= � igual que dizer NOT EQUAL
LIKE permite procurar uma cadeia dentro de uma coluna com comodines :
WHERE coluna LIKE '%Pepito%'
El % � um comodim, no exemplo, ser� verdadeiro se "Pepito" est� na string.
WHERE coluna LIKE 'Pepito%'
WHERE coluna LIKE '%Pepito'
ser� verdeiro se "Pepito" est� no final da string.
Por aqui todas as op��es poss�veis do WHERE sai de minhas poss�bilidades e tempo, s�
cabe aqui dizer que o limite est� na m�quina do programador e os limites do pr�prio
tradutor do gerenciador.
Agora podemos deixar o comando SELECT e centrarmos nos dois �ltimos.
Comando update
O comando update permite modificar uma ou v�rias tabelas, dependendo da condi��o
no WHERE.
SINTAXE
UPDATE tabela SET coluna-1 = expres�o-1
[, coluna-i = expres�o-i]
[WHERE condi��o]
Onde :
tabela : � a tabela para modificar, s� poderemos modificar uma tabela por vez
coluna : � a coluna a ser modificada
expres�o : � o valor que vai receber a coluna, este valor pode ser est�tico ou o resultado de uma fun��o
condi��o : � a condi��o que define o ambito do trabalho da modifica��o, aqui s�o
aplicadas todas as regras definidas para o comando SELECT
Comando delete
O comando DELETE permite modificar uma ou v�rias colunas de uma tabela.
SINTAXE
DELETE FROM tabela
[WHERE condi��o]
Onde :
tabela : |
� a tabela onde vamos apagar, s� podemos apagar uma tabela por vez |
condi��o : |
� a condi��o que define o ambito de trabalho de exclus�o, aqui s�o aplic�veis
todas as regras definidas para o SELECT
NOTA : se n�o existir WHERE, DELETE eliminar� todas as colunas da tabela.
|
Referencias
Outros artigos do autor
|