Buscar

Implementação de banco de dados (Recuperação Automática)

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 145 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 145 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 145 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Implementação de banco de dados
· Álgebra relacional
Nesta aula, você vai estudar o Modelo Relacional e a Álgebra Relacional. No mundo digital, nossas vidas são regidas por diversos sistemas. Para funcionar, esses sistemas necessitam de grande volume de dados. Os sistemas informatizados evoluíram ao longo do tempo de Sistemas Baseados em Arquivos para Sistemas Baseados em Banco de Dados.
Não é possível conceber, atualmente, qualquer sistema que possa prescindir de um Banco de Dados. Os Sistemas de Banco de Dados atuais são, majoritariamente, baseados no Modelo Relacional.
Entretanto, de que adiantaria termos uma estrutura de armazenamento se não conseguíssemos manipular os dados ali armazenados? Como o modelo relacional teve sua origem na matemática, essa mesma ciência nos fornece a ferramenta para manipulá-lo, a Álgebra Relacional.
 
A evolução da tecnologia associada ao grande aumento do volume de dados a ser armazenado e processado levou à criação de uma nova abordagem para o problema, o Sistema de Banco de Dados.
Um banco de dados é uma coleção de dados organizados de tal forma que possam ser acessados e utilizados por muitas aplicações diferentes. Ou seja, em vez de armazenar dados em arquivos separados para utilização, os dados são armazenados e organizados em um só local, permitindo compartilhamento e inter-relacionamento por múltiplos usuários.
A fim de usar a abordagem de banco de dados para o gerenciamento de dados, foi necessário um software adicional – um sistema de gerenciamento de banco de dados (SGBD). O SGBD consiste em um grupo de programas que podem ser usados como uma interface entre o banco de dados e um usuário ou um banco de dados e um programa aplicativo.(Fig 2)
Modelo relacional
Nos maiores SGBD comerciais, o modelo de dados utilizado é o Modelo Relacional criado com base na Teoria Matemática dos Conjuntos e na Álgebra Relacional, O Modelo de Dados Relacional tem as seguintes vantagens:
· É independente das linguagens de programação;
· É independente dos sistemas de gestão de bases de dados;
· É independente dos Sistemas Operacionais.
Da afirmativa acima. pode-se depreender uma relação como uma tabela de valores onde cada linha representa uma coleção de dados ou valores relacionados. Cada linha da tabela representa uma realidade ligada ao mundo real. O nome da tabela e o nome das colunas são definidos de forma que representem essa realidade. Pode-se ter uma tabela chamada ALUNO onde cada linha venha a ser o Nome de um Aluno a ser armazenado.
Podemos melhorar ainda mais essa representação, criando uma tabela com as colunas NOME, NÚMERO DE MATRÍCULA e CLASSE. Cada linha da tabela representa várias informações de um ALUNO e cada coluna isoladamente, representa uma informação específica desse aluno. Assim o nome da tabela e os nomes das colunas são capazes de dizer o que cada linha representa e também o que o conjunto representa.
No modelo relacional formal (Figura 3), cada linha é chamada de tupla, o nome da coluna é conhecido como atributo ou variável, e a tabela, relação. (FONSECA, 2016)
Álgebra relacional
É o conjunto básico de operações para o modelo relacional. Essas operações permitem a recuperação de tuplas mediante instruções de consulta aplicadas ao banco de dados. O resultado dessa recuperação também será uma relação, que pode ser usada em outras operações de consulta.
A importância da álgebra relacional:
· Provê fundamento formal para operações do modelo relacional;
· Alguns de seus conceitos são incorporados na linguagem SQL padrão.
· E o mais importante: é usada como base para implementar e otimizar as consultas em sistemas de banco de dados relacional. (FONSECA, 2016, p. 15)
As principais operações da álgebra relacional são:
Operação de seleção
A operação de Seleção recupera os dados de uma ou mais tabelas, selecionando um subconjunto de tuplas que satisfaça determinada condição de seleção. Essa condição de seleção é usada para dividir horizontalmente uma relação em dois conjuntos de tuplas – as tuplas que satisfazem a condição e são retornadas e as tuplas que não satisfazem a condição e são ignoradas. (FONSECA, 2016, p.16)
A forma geral de uma operação de seleção é:
(nome da relação) <condição de seleção> σσ
Onde:
• <condição de seleção> é a condição que a linha deve atender para ser selecionada.
Constituindo-se em uma expressão lógica, é construída a partir de cláusulas da forma:
<nome de atributo> <operador de comparação> <valor constante >, ou
<nome de atributo> <operador de comparação> <nome de atributo >
Onde:
<nome de atributo> é um atributo da relação definida em <nome da relação>
<operador de comparação> é normalmente um dos operadores relacionais {=, <, ≤, ≥, ≠} e
<valor constante> é um literal.
As cláusulas podem ser utilizadas em conjunto com os operadores lógicos {AND, OR NOT}, seguindo a Lógica Booleana, para formar uma condição de seleção composta.
<nome da relação> é o nome da relação sobre a qual será aplicada a operação de Seleção
A relação resultante da operação tem os mesmos atributos da relação especificada em <nome da relação>.
Operação de Projeção
A operação de Projeção recupera os dados de certas colunas de uma tabela e descarta outras. Se existir a necessidade de mostrar apenas alguns atributos de uma tabela em detrimento de outros, usa-se a operação PROJEÇÃO. (FONSECA, 2016, p. 17)
A forma geral da operação de projeção é:
ππ <lista de atributos> (<nome da relação>)
Onde:
<lista de atributos> representa a lista de atributos que o usuário deseja selecionar e
<nome da relação> representa a relação sobre a qual a operação projeção será aplicada.
Sequencialidade de Operações
A Projeção e a Seleção podem ser combinadas, de forma que apenas algumas linhas e algumas colunas retornem na operação. A forma geral de uma operação sequencializada é:
ππ <lista de atributos> (σσ <condição de seleção> (<nome da relação>) )
Onde:
ππ representa a operação de projeção;
<lista de atributos> representa a lista de atributos que o usuário deseja selecionar;
σσ representa a operação de seleção;
<condição de seleção> é a condição que a linha deve atender para ser selecionada;
<nome da relação> é o nome da relação sobre a qual será aplicada a operação de Seleção e Projeção
Operação Produto Cartesiano
Operação Junção
A operação Join (Junção) é usada para combinar as tuplas relacionadas em duas relações dentro de uma única tupla. Essa operação é uma das mais importantes em um banco de dados relacional, pois ela nos permite retornar os relacionamentos entre as relações (tabelas).
A forma geral da operação junção entre duas tabelas A e B é a seguinte:
A X B
<condição de junção>
Onde: <condição de junção> é uma expressão relacional, normalmente utilizando o operador =, que determina qual coluna da tabela A deve ser comparada com qual coluna da tabela B.
Observação: normalmente as colunas envolvidas na condição de junção são a Chave Primária de uma tabela e a Chave Estrangeira na outra.
Operação de Conjuntos
São operações derivadas das operações matemáticas padrão definidas a partir da teoria dos conjuntos. (FONSECA, 2016, p. 18)
São elas:
UNION
UNION é a operação de UNIÃO da teoria de conjuntos. Se temos as relações R(A1, A2, ..., An) e S(B1, B2, ..., Bn) para haver a operação União, os atributos de cada relação devem ser compatíveis entre si, ou seja, devem ter o mesmo grau (n) e os domínios de cada atributo devem ser iguais ao domínio do outro atributo, ou seja, dom(A1) = dom(B1). Significando que cada relação possui o mesmo grau e que cada par de atributos possuem o mesmo domínio. Sendo assim, a operação UNION pode ser aplicada. (FONSECA, 2016, p. 18)
A forma geral da operação junção entre duas tabelas A e B é a seguinte:
A U B
A Operação de União é comutativa, ou seja, A U B produz o mesmo resultado de B U A.
Exemplo: Temos a tabela DISCIPLINA_NOTA (Fig 4) e a nova tabela PROFESSOR (Fig10). Podemos fazer a união dos domínios ‘NOME_PESSOA’ com os nomes dos alunos e os nomes dos professores.
INTERSECTION
Da mesma forma comofoi apresentada a operação UNION, pode-se usar a definição matemática de interseção para definirmos a operação de interseção entre as relações. As observações feitas para a operação UNION, no que diz respeito ao domínio dos atributos e ao grau da relação, também devem ser seguidas para a operação de INTERSECTION. (FONSECA, 2016, p. 20)
A ∩ B
Essa operação é comutativa, ou seja, A ∩ B produz o mesmo resultado de B ∩ A.
Exemplo: De acordo com Fonseca (2016), para a interseção entre os nomes de professores e alunos, temos:
ππ NOME_ALUNO (DISCIPLINA_NOTA) U PROFESSOR
MINUS
Por fim, apresentamos a operação MINUS (SUBTRAÇÃO), que representa a diferença de conjunto. O resultado dessa operação, tomando-se nossas relações S e R apresentadas anteriormente, é uma relação que inclui todas as tuplas que estão em R, mas não estão em S. As observações feitas para a operação UNION e INTERSECTION, no que diz respeito ao domínio dos atributos e ao grau da relação, também devem ser seguidas para a operação MINUS. (FONSECA, 2016, p. 20)
A forma geral da operação Diferença entre duas tabelas A e B é a seguinte:
A - B
Essa operação não é comutativa, ou seja, A - B produz um resultado diferente de B – A.
Para obtermos o nome dos Professores que não são homônimos de alunos (FONSECA, 2016, p. 20), a expressão seria:
PROFESSOR - ππ NOME_ALUNO (DISCIPLINA_NOTA)
Resultando:
Exercícios
5. Considerando a tabela a seguir, marque todas as opções que atendam à consulta solicitada como correta ou errada e justifique.
Listar o nome e o salário dos empregados que ganham mais de R$ 2.000,00 .
 
· Linguagem SQL
Linguagem SQL
O padrão mundial de acesso a banco de dados é a Linguagem Estruturada de Consulta (Structured Query Language) ou simplesmente SQL, na sigla em inglês.
A linguagem SQL divide-se em partes, cada uma atendendo a uma necessidade específica. Temos, então, a seguinte divisão:
Nosso foco de estudo será nos comandos de criação, alteração e eliminação de tabelas e nos comandos de DML (Insert, Update, Delete e Select).
Tabelas
Tabelas são os objetos básicos de armazenamento de dados no modelo relacional. Para criarmos uma tabela, devemos definir o seu nome, suas colunas, os tipos de dados das colunas e suas restrições.
Nome
O nome da tabela é normalmente definido durante a modelagem lógica, constituindo às vezes, alguma variação em relação ao nome da entidade. Por exemplo, entidade Aluno vira tabela Aluno ou Alunos.
É importante conhecer as limitações do SGBD na hora de criar a tabela. A maior parte dos SGBD não dão suporte a caracteres em português no nome da tabela. Dessa forma, se temos uma entidade Aprovação, teremos que criar a tabela Aprovacao; se a entidade tem o nome Prova Aluno, teremos que substituir o espaço em banco por: _ Prova_Aluno.
Colunas
As colunas das tabelas se originaram dos atributos das entidades conforme vimos na modelagem lógica. Da mesma forma que o nome da tabela, temos que respeitar as limitações do SGBD: não usar espaço em branco, caracteres em português e nos preocupar também com a quantidade máxima de caracteres que o nome da coluna ou tabela pode ter. Muitas vezes, por causa dessa limitação, teremos que abreviar o nome. Por exemplo: o atributo Matrícula do Aluno poderá virar a coluna Mat_Aluno na tabela.
Tipos de dados
As colunas possuem um tipo de dado que podem armazenar de forma similar ao conceito de tipo utilizado nas variáveis criadas em programas.
Os SGBD possuem uma variedade muito grande de tipos. Cada SGBD tem o seu conjunto específico, que é, muitas vezes, incompatível com outros SGBD. Nós faremos uso do PostGreSql como SGBD para a realização de exercícios. Nos comandos de criação de tabelas, os tipos básicos são:
Esses tipos mostrados na tabela acima são uma pequena parte dos tipos existentes no PostgreSql, mas serão suficientes para nossos exercícios.
NOTA:
Abordaremos também as particularidades do SQL do Oracle e do SQL Server no que diferem do PostgreSql.
Restrições
As restrições, normalmente chamadas constraint visam estabelecer regras para orientar o SGBD na forma de manter a integridade do banco.
Aqui vamos tratar das seguintes constraint:
Comando de criação de tabela
O comando de Criação de Tabela é o Create Table.
Vejamos sua sintaxe:
CREATE TABLE nome_da_tabela(
(nome_col1 tipo_col1 [restri_col1] [,
nome_col2 tipo_col2 [restri_col2] [,
nome_coln tipo_coln [restri_coln] [,
restri_tab1 [restri_tab2]);
	
Onde:
Vamos ver um exemplo de criação.
Considere a tabela Departamento:
O comando que a criaria no PostGreSql seria:
CREATE TABLE DEPARTAMENTO
(ID NUMERIC(7) PRIMARY KEY,
NOME VARCHAR(40) NOT NULL)
Observe no comando a constraint PRIMARY KEY, definindo a coluna ID como chave primária e a constraint NOT NULL, estabelecendo que NOME é de preenchimento obrigatório.
Sugiro que você crie a tabela no PostGreSql conforme as orientações do vídeo da aula.
Para vermos a tabela criada, a forma mais fácil é consultarmos o conteúdo de toda a tabela. Para isso, podemos dar o comando:
SELECT *
FROM DEPARTAMENTO
Esse comando é básico e lista todo o conteúdo da tabela.
Note que a tabela está vazia, mas foi criada no banco com duas colunas.
No SQL Server, o comando é o mesmo.
O comando funciona também no Oracle:
Mais Constraints
Campos únicos
UNIQUE
Ao estabelecermos a constraint UNIQUE para uma coluna, determinamos que ela não pode ter valor repetido. Entretanto, ela não obriga a coluna a ter valor ou não a torna de preenchimento obrigatório e, como NULO não é valor, uma coluna UNIQUE pode possuir várias linhas nulas (sem valor).
Exemplo
CPF char(11) UNIQUE,
Reforçando a Integridade Referencial com Chave Estrangeira (Foreign Key)
Foreign Key
Os relacionamentos entre tabelas são criados através da geração de chaves estrangeiras (foreign key – FK) nas tabelas FILHO que referenciam colunas chaves nas tabelas PAI.
Para estabelecer essa restrição, acrescentamos REFERENCES na definição da coluna, como exemplo:
ID_DEPTO numeric (7) References Departamento(ID),
Onde:
· Id_depto é o nome da coluna;
· Numeric r(7) o tipo da coluna;
· References identifica a restrição de chave estrangeira;
· Departamento é o nome da tabela para onde aponta a chave estrangeira;
· (ID) é coluna da tabela departamento apontada pela chave estrangeira.
Vejamos um exemplo de criação de tabela com essas restrições.
CREATE TABLE EMPREGADO
( ID NUMERIC(7) PRIMARY KEY,
ULT_NOME VARCHAR(20) NOT NULL,
PRIM_NOME VARCHAR(20) NOT NULL,
CARGO VARCHAR(30),
SALARIO NUMERIC(7,2),
DT_ADMISSAO DATE,
CPF CHAR(11) UNIQUE,
ID_DEPTO NUMERIC(7) REFERENCES DEPARTAMENTO(ID))
Observe o comando. Através de sua análise, podemos observar que:
- a coluna ID é sua chave primária;
- As colunas ULT_NOME e PRIM_NOME são de preenchimento obrigatório;
- A coluna CPF é única;
- A coluna ID_DEPTO é uma chave estrangeira para a tabela departamento.
Vamos criá-la no PostGgreSql.
Observe a mensagem de sucesso.
Atenção
Importante
Se uma tabela possui uma chave estrangeira para outra, ela tem que ser criada depois da tabela referenciada, senão ocorrerá um erro.
Vamos agora criar uma terceira tabela:
CREATE TABLE CLIENTE
( ID NUMERIC(7) PRIMARY KEY,
NOME VARCHAR(40) NOT NULL,
VENDEDOR NUMERIC(7))
Acrescentando colunas em tabelas
Podemos acrescentar colunas em tabelas já criadas com o comando Alter Table. Sua sintaxe é:
alter table <nome_tabela> add <nome_coluna> <tipo da coluna> <constraint >
Em que:
<nome_tabela> é o nome da tabela a qual será acrescida à coluna.
<nome coluna> é o nome da coluna que será acrescida.
<tipo da coluna> é o tipo de dado da coluna a ser acrescida.
<constraint> é a restrição, se for o caso, da coluna a ser acrescida.
Exemplo
Na criação da tabela Departamento. Vimos que duas restrições (constraints) são estabelecidas como: uma de obrigatoriedade (NOT NULL) e uma Chave Primária.
Vamos assumir, entretanto que nossa tabela, com esse último comando de criação, não foi completamente estabelecida. Está faltando a coluna descrição. Para inseri-la, podemos dar o comando:
ALTER TABLE DEPARTAMENTO ADD descricao VARCHAR(30)NOT NULL;
Vamos executar o comando. Para isso, digite-o no PostgreSql.
Eliminando colunas de tabelas
É possível eliminar colunas de tabelas, inclusive aquelas referenciadas por constraints e índices, e até mesmo chaves primárias, únicas e estrangeiras. É verdade que cuidados quanto à aplicação devem ser tomados por parte dos desenvolvedores e DBA, porém, o SGBD implementa essa funcionalidade.
Ao eliminarmos uma coluna, suas restrições, caso existam, também são removidas do dicionário de dados.
Sintaxe:
alter table <nome_tabela> drop column <nome_coluna>;
Em que:
<nome_tabela> é o nome da tabela da qual será eliminada a coluna.
<nome coluna> é o nome da coluna que será eliminada.
Por exemplo: se desejarmos eliminar a coluna descrição da tabela Departamento, daremos o seguinte comando:
ALTER TABLE DEPARTAMENTO DROP COLUMN DESCRICAO
Vamos executar o comando. Para isso, digite-o no PostgreSql.
Incluindo uma Foreign Key numa tabela existente
Também podemos incluir a constraint de Foreign Key após a criação da tabela. Para tal, basta especificar a adição da constraint no comando ALTER TABLE.
A tabela Cliente foi criada, mas a coluna Vendedor deveria ser uma chave estrangeira para a tabela Empregado na coluna ID. Podemos dar o seguinte comando de ALTER TABLE:
ALTER TABLE CLIENTE ADD FOREIGN KEY (VENDEDOR) REFERENCES EMPREGADO(ID)
Em que:
CLIENTE – é a tabela a ser alterada
ADD FOREIGN KEY – é a restrição a ser acrescida.
(VENDEDOR) é a coluna que receberá a constraint
REFERENCES EMPREGADO(ID) indica a tabela e a coluna referenciadas pela chave estrangeira.
Veja o comando no PostGreSql.
Constraint de colunas e tabelas
As constraints podem ser definidas junto com a coluna ou separadamente, no final do comando create table ou com o comando alter table. As constraints not null só podem ser definidas junto com a definição da coluna.
As constraints de tabela são utilizadas principalmente para criar constraints compostas, onde duas ou mais colunas fazem parte da constraint. Como, por exemplo, chaves primárias compostas.
Exemplo: A tabela Turmas possui uma chave primary composta pelas colunas CODIGO_TURMA e CODIGO_CURSO. O comando para sua criação é:
CREATE TABLE TURMAS
(CODIGO_TURMA NUMBER(6),
CODIGO_CURSO NUMBER(3),
CODIGO_FUNCIONARIO NUMBER(6),
DATA_INICIO DATE,
DATA_FIM DATE ,
SALA NUMBER(2),
PRIMARY KEY (CODIGO_TURMA, CODIGO_CURSO) );
E se desejarmos apagar uma tabela?
Para isso temos o Comando Drop, cuja sintaxe é:
DROP TABLE <NOME DA TABELA>
Para eliminarmos a tabela TURMAS, daremos o comando:
DROP TABLE TURMAS;
Execute o comando no PostGreSql.
Observe a mensagem de sucesso.
Agora, se dermos o comando de Select na tabela, teremos uma mensagem de erro.
Veja o que acontece ao eliminar a tabela Departamento.
Não será possível porque a tabela Empregado possui uma Chave Estrangeira para Departamento, e você não poderá eliminar Departamento enquanto essa FK existir.
Atenção
Os comandos de CREATE TABLE, ALTER TABLE e DROP TABLE vistos aqui funcionam de forma exatamente igual no PostGreSql, no Oracle e no Sql Server.
Manipulando dados
Agora que já você já aprendeu a criar, alterar e eliminar tabelas, vai estudar os comandos de manipulação de dados que permitirão que você faça a inclusão, alteração ou eliminação das linhas das tabelas.
Esses comandos são:
Insert – para incluir linhas; Delete – para eliminar linhas; Update – para alterar linhas.
 
Inserindo Linhas
 Clique no botão acima.
Inserindo Linhas
O comando INSERT insere linhas em uma tabela.
Sua sintaxe básica é:
insert into .<nome_tabela> (coluna1, coluna2, ..., colunan)
values (valor1, valor2, ..., valorn);
Em que:
	Cláusula
	Descrição
	nome_tabela
	O nome da tabela a ser atualizada
	Coluna n
	A coluna que queremos inserir
	Valor n
	É o novo valor associado à coluna a ser inserida
Vamos inserir uma linha na tabela de departamento.
INSERT INTO DEPARTAMENTO (ID, NOME)
VALUES (100, 'Financeiro');
A relação entre a lista de colunas (ID, NOME) e a lista de valores (100, 'VENDAS) é posicional, portanto:
· A coluna ID receberá o valor 100;
· Nome receberá Vendas.
Execute o comando no PostgreSql e observe a mensagem de linha inserida.
Uma outra forma de dar o comando INSERT é sem referenciar as colunas. Nesse caso, a lista de valores deve estar na ordem das colunas da tabela.
INSERT INTO DEPARTAMENTO VALUES (200, 'Compras')
Desta vez, não foram especificadas as colunas que receberão os valores. Portanto, o comando utilizará todas as colunas da tabela na ordem em que foram criadas.
A nossa tabela possui duas linhas.
lnserindo com valores nulos
Caso alguma coluna deva ficar com NULO em uma inserção, basta omitir o nome da mesma na lista de colunas. Vejamos um exemplo em que isso ocorre:
No exemplo acima, foram omitidas as colunas CARGO, SALARIO, DT_ADMISSAO e CPF, que ficaram nulas.
Atenção
Observe que NULO não é equivalente a 0 (zero), espaço ou qualquer outro valor. NULO é, justamente, a ausência de qualquer valor na coluna.
Um cuidado que devemos ter é que só é possível fazer isso em colunas que não possuam a constraint NOT NULL. Outro detalhe é que nenhuma coluna definida como chave primária poderá conter NULO.
No nosso exemplo, se não fosse especificado um valor para a coluna id, a inserção resultaria em erro. O mesmo erro ocorreria se não tivéssemos valores para as colunas PRIM_NOME e ULT_NOME, já que são de preenchimento obrigatório (constraint not null).
Aproveitando ainda esse exemplo de inserção, note que inserimos o PRIM_NOME e depois o ULT_NOME, apesar de na tabela ULT_NOME vir antes de PRIM_NOME. Isso foi possível devido à inserção ser realizada na ordem da lista de colunas.
Uma última observação se refere à Chave Estrangeira ID_DEPTO, cujo valor inserido OBRIGATORIAMENTE tem que existir na tabela DEPARTAMENTO.
Outra forma de inserirmos com valores nulos em uma coluna é utilizando a palavra reservada null. Vejamos um exemplo:
Como omitimos a lista de colunas, temos que ter um valor para cada coluna. Então estamos inserindo 20 no ID, Fonseca no Prim_Nome, Antonio no Ult_Nome no NOME , nulo nas colunas CARGO, SALARIO, DT_ADMISSAO e CPF e 200 no Id_depto.
Execute o comando.
Observe a mensagem de linha inserida.
Como omitimos a lista de colunas, temos que ter um valor para cada coluna, na ordem das colunas da tabela.
Você também pode executar vários comandos de inserção juntos; Basta separá-los por:
INSERT INTO EMPREGADO
VALUES (2, 'Neves', 'Lauro', 'Diretor de Compras',19500, '07/03/2009','23456789012',200);
INSERT INTO EMPREGADO
VALUES (3, 'Nogueira', 'Mário','Diretor de Vendas', 18000, '07/04/2010','34567890123',100);
INSERT INTO EMPREGADO
VALUES (4, 'Queiroz', 'Mark','Gerente de Compras',8000, '07/11/2010','12345432123',200);
INSERT INTO EMPREGADO
VALUES( 5, 'Rodrigues', 'Alberto', 'Vendedor',4000, '10/1/2008', '87965432123', 100);
INSERT INTO EMPREGADO
VALUES( 6, 'Ugarte', 'Marlene', 'Vendedor', 3500,'23/11/2009', '87654345678',100);
Como resultado, temos sete linhas na tabela.
Observe que apesar de termos inserido a data no formato DD/MM/AAAA, o PostgreSql sempre exibe por padrão no formato AAAA/MM/DD. Você pode dar o comando de inserção de uma forma ou de outra, mas, para evitar problemas, use sempre AAAA/MM/DD. É mais seguro.
Atualizando linhas
O comando UPDATE permite que atualizemos dados já existentes nas tabelas.
Sua sintaxe é:
UPDATE nome_tabela
SET coluna = expressão
WHERE condição
Onde:
	Cláusula
	Descrição
	Nome_tabela
	O nome da tabela a ser atualizada.
	coluna
	A coluna que queremos alterar.
	expressão
	O novo valor associado à coluna a ser alterada.
	condição
	A condição que deverá satisfazer as colunas que serão alteradas.
Vejamos um exemplo:
Vamos aumentar o salário de todos empregados em R$ 1000.
UPDATE EMPREGADO
SET SALARIO = SALARIO + 1000;
Como resultado teríamos:
Repare que:
1. Como o comando foi dado sem cláusula where, ele afetou todas as linhas da tabela;
2. Os empregados de id 10 e 20 continuaram com salário nulo. Isso ocorre porque Nulo não é valor, e qualquer valor operado com Nulo tem comoresultado Nulo.
Mas vamos agora atribuir um salário a esses dois empregados. Podemos então dar um comando de UPDATE com WHERE para alterar apenas essas duas linhas.
UPDATE EMPREGADO
SET SALARIO = 3000
WHERE ID = 10 OR ID = 20;
Vejamos como ficou:
Repare que os empregados 10 e 20 possuem salário.
Eliminando linhas
O comando DELETE é utilizado para excluir linhas em uma tabela e tem como sintaxe:
DELETE FROM nome_tabela
WHERE condição
Em que:
	Cláusula
	Descrição
	Nome_tabela
	O nome da tabela a ser deletada
	condição
	A condição que deverá satisfazer as colunas que serão deletadas
Vamos apagar da Tabela Empregado o funcionário de ID 10.
DELETE FROM EMPREGADO
WHERE ID = 10;
Dessa forma, o resultado seria não ter mais a linha do empregado 10 na tabela.
Atenção
1. Se você desse o comando de delete na Tabela Empregado sem a Cláusula Where, TODAS AS LINHAS da tabela seriam apagadas.
2. Você não consegue apagar linhas na tabela Departamento enquanto existirem linhas em Empregado que as referenciem na Chave Estrangeira.
Vamos, agora, reconstituir nosso ambiente, eliminando as tabelas Departamento e Empregado na ordem correta:
· DROP TABLE CLIENTE;
· DROP TABLE EMPREGADO;
· DROP TABLE DEPARTAMENTO.
Você deve dropar as tabelas nessa ordem devido às FK.
Scripts
Um SCRIPT nada mais é que um conjunto de comandos SQL salvos em um arquivo com a extensão .sql, que é carregado no SGBD. Em seguida, é lido e tem seus comandos executados como um todo.
No PGADMIN, podemos carregar um Script clicando em Abrir Arquivo.
Navegando até o local do arquivo e o selecionando.
Feito isso, o conteúdo do Script é carregado e basta mandar executá-lo.
As tabelas são criadas e os dados inseridos.
Atividade
1. A partir do Modelo Lógico a seguir, crie as tabelas no PostGreSql.
2. Insira os dados nas tabelas criadas na atividade 1 de forma que as tabelas fiquem conforme as figuras a seguir:
· Linguagem SQL – Select – Parte 1
Banco de Dados de exemplo
Um banco de dados denominado ”Empresa” será utilizado para os exemplos desta aula e das próximas. O Banco da empresa possui o seguinte Modelo Lógico:
As tabelas possuem os seguintes dados:
Comandos para criação de tabelas:
CREATE TABLE REGIAO
(ID_REGIAO NUMERIC(7) PRIMARY KEY,
 NOME  VARCHAR(40));
CREATE TABLE DEPARTAMENTO
( ID NUMERIC(7) PRIMARY KEY,
NOME VARCHAR(40) NOT NULL,
ID_REGIAO NUMERIC(7 )REFERENCES REGIAO(ID_REGIAO));
CREATE TABLE EMPREGADO
( ID NUMERIC(7) PRIMARY KEY,
 ULT_NOME VARCHAR(20) NOT NULL,
PRIM_NOME  VARCHAR(20) NOT NULL,
CARGO VARCHAR(30),
SALARIO NUMERIC(7,2),
DT_ADMISSAO DATE,
CPF CHAR(11) UNIQUE,
ID_DEPTO NUMERIC(7) REFERENCES DEPARTAMENTO(ID),
ID_GERENTE NUMERIC(7) REFERENCES EMPREGADO(ID));
CREATE TABLE CLIENTE
( ID NUMERIC(7) PRIMARY KEY
NOME VARCHAR(40) NOT NULL,
VENDEDOR NUMERIC(7) REFERENCES EMPREGADO(ID));
INSERINDO LINHAS NA TABELAS
INSERT INTO REGIAO VALUES (1, 'Norte');
INSERT INTO REGIAO VALUES (2, 'Sul');
INSERT INTO DEPARTAMENTO VALUES (10, 'Administrativo',1);
INSERT INTO DEPARTAMENTO VALUES (20, 'Vendas',1);
INSERT INTO DEPARTAMENTO VALUES (30, 'Compras',2);
INSERT INTO EMPREGADO VALUES (1, 'Velasques', 'Carmen', 'Presidente',29500, '05/05/2009','34567890125',10, null);
INSERT INTO EMPREGADO VALUES (2, 'Neves', 'Lauro', 'Diretor de Compras',19500, '03/03/2009','23456789012',30,1);
INSERT INTO EMPREGADO VALUES (3, 'Nogueira', 'Ernane','Diretor de Vendas', 18000, '07/04/2010','34567890123',20,1);
INSERT INTO EMPREGADO VALUES (4, 'Queiroz', 'Mark','Gerente de Compras',8000, '11/11/2010','12345432123',30,2);
INSERT INTO EMPREGADO VALUES (5, 'Rodrigues', 'Alberto', 'Vendedor',4000, '10/10/2008', '87965432123', 20,3);
INSERT INTO EMPREGADO VALUES (6, 'Ugarte', 'Marlene', 'Vendedor', 3500,'03/03/2009', '87654345678',20,3);
INSERT INTO CLIENTE VALUES (110, 'Ponto Quente',5);
INSERT INTO CLIENTE VALUES (120, 'Casa Supimpa',6);
INSERT INTO CLIENTE VALUES (130, 'Coisas e Tralhas',5);
INSERT INTO CLIENTE VALUES (140, 'Casa Desconto',null);
Comentário
Os comandos listados acima mostram como o script disponível funciona normalmente no postgreSql e no SqlServer. No ORACLE, deve ser comandado COMMIT após o último insert.
Tendo esse Banco em mente, é altamente recomendável que você execute os comandos de exemplo no PostGreSql.
Foi escolhido como base o PostgreSql, por ser um SGBD mais leve e fácil de instalar, porém, se você  puder usar o SqlServer ou o Oracle quando houver diferença entre os SGBD’s, será avisado.
Consultando dados de uma tabela
O comando SQL que permite recuperar dados de uma ou mais tabelas é o SELECT. Esse comando nos permite escolher as colunas que retornarão, bem como filtrá-las da tabela.
O comando de Select é uma implementação prática da teoria dos conjuntos, mais especificamente da Álgebra Relacional. Dessa forma, um único Select pode retornar zero ou várias linhas, de acordo com as restrições colocadas no comando.
Os componentes básicos do comando são:
 
SELECT e FROM
 Clique no botão acima.
Cláusula SELECT
· Lista as colunas que serão recuperadas;
· Se utilizarmos o artifício do * (asterisco) na cláusula SELECT, estaremos definindo que todas as colunas serão recuperadas.
Cláusula FROM
· Define a tabela que será recuperada.
Veja a sintaxe abaixo:
SELECT nome-col1, nome_col2, nome coln
FROM    nome_da_ tabela;
OU
SELECT *
FROM    nome_da_tabela ;
Em que:
	Palavra-Chave
	Descrição
	nome_da_tabela
	Nome da tabela que contém os dados a serem recuperados.
	nome_coln
	Nome de uma coluna a ser recuperada.
	* (asterisco)
	Recupera todas as colunas da tabela.
Retornando uma tabela inteira
Acesse o SGBD e digite o seguinte comando:
SELECT * FROM EMPREGADO.
No comando acima, selecionamos todas as colunas e todas as linhas da tabela EMPREGADO.
Teremos uma resposta semelhante à figura 1.
 Figura 1 – Retorno do Comando
Observe que não há nenhuma ordem ou seleção de linhas ou colunas.
Retornando colunas específicas
Na Álgebra Relacional, vimos que existe a operação de projeção que  permite retornar apenas algumas colunas da tabela, mas todas as linhas. O mesmo pode ser obtido em SQL. Para isso basta que se liste as colunas desejadas na cláusula SELECT, separando-as por virgulas.
Veja um exemplo:
Acesse o SGBD e digite o seguinte comando:
SELECT ID, PRIM_NOME, ULT_NOME FROM EMPREGADO.
No comando acima, são selecionadas apenas três colunas e todas as linhas da tabela EMPREGADO, e o seu retorno pode ser observado na Fig2.
 Figura 2 – Retorno do Comando
Comentário
Nesse segundo caso, não são exibidas as colunas CARGO, SALARIO, DT_ADMISSAO, CPF,ID_DEPTO e ID_GERENTE.
No primeiro comando analisado, um asterisco substitui a lista de colunas desejadas, indicando que todas as colunas devem ser informadas.
Exemplos:
Como seria o comando para exibir todo o conteúdo da tabela departamento, cujo retorno é exibido na fig3?
 Figura 3 – Retorno do Comando
Dica: tente dar o comando no SGBD antes de ver a SOLUÇÃO.
CONTEÚDO SOLUÇÃO
Como seria o comando para exibir todo o NOME e o ID de todos os clientes, cujo retorno é exibido na fig4?
 Figura 4 – Retorno do Comando
Dica: tente dar o comando no SGBD antes de ver a SOLUÇÃO.
CONTEÚDO SOLUÇÃO
Dica
Note que:
· Quando você utiliza *, as colunas retornam na ordem em que foram criadas na tabela;
· Quando você lista as colunas no SELECT, elas retornam na ordem em que as listou;
· As colunas no SELECT devem estar separadas por vírgula;
· Não deve existir vírgula antes da cláusula FROM.
 
SELECT
 Clique no botão acima.
Incrementando a consulta
Para efetuar consultas mais complexas e derivar dados a partir das informações contidas nas tabelas, você pode construir expressões na cláusula SELECT.
As expressões podem ser aritméticas ou alfanuméricas, fazendo concatenações por exemplo.
Uma expressão aritmética pode conter os seguintes operadores:
*  multiplicação;
/ divisão;
+  adição;
-  subtração.
Para concatenarmos duas colunas, utilizamos o operador || OU + dependendo do SGBD.
Escrevendo expressões aritméticas em comando Select
Em uma expressão, podemos especificar não apenas uma coluna,mas um dado derivado de uma ou mais colunas.
Exemplo
A figura 5 mostra a tabela Empregado. Como ficaria então o comando que listaria o ID, o Ult_NOME, o Salário e o salário anual (consideramos que o salário anual é o salário mensal multiplicado por doze) de todos os empregados?
 Figura 5 – TABELA EMPREGADO
O comando pode ser visto na figura 6:
 Figura 6 – COMANDO E RETORNO
Esse comando funciona da mesma forma no PostGreSql, SqlServer e Oracle.
Escrevendo expressões de concatenação
No PostGreSql, o operador de concatenação é o ||. Se desejássemos retornar o PRIM_NOME do empregado com o ULT_NOME, o comando seria:
SELECT PRIM_NOME || ULT_NOME
FROM EMPREGADO
O retorno seria o exibido na Fig7.
 Figura 7 – RETORNO DO COMANDO
Analise a figura 7. Notou que os nomes estão colados?
Isso decorre do fato de que, depois do PRIM_NOME ou antes do ULT_NOME, não existe espaço em branco armazenado na coluna. 
Como resolver isso?
Basta concatenar as colunas com um espaço em branco entre elas, conforme mostra a Figura 8.
 Figura 8 – COMANDO E RETORNO
Mas você pode se perguntar: como fica isso no Oracle e no Sql Server?
No Oracle, o operador é o mesmo (Figura 9).
 Figura 9 – COMANDO E RETORNO
Já no SqlServer, o operador de concatenação é o + (Figura 10).
 Figura 10 – COMANDO E RETORNO
Criando Alias
Quando são utilizadas expressões, o cabeçalho da coluna, normalmente, fica sem significado.
Dependendo do SGBD, ele pode ser a própria expressão, como acontece no ORACLE, pode ser (No column name), como acontece no SQLSERVER, ou pode ser? column?
Como acontece no PostgreSQL (Figura 11).
Seja como for, seria mais interessante se fosse possível nomear as colunas de forma a manterem o seu significado. Para isso, existem os alias de coluna.
	PostGreSql
	SqlServer
	Oracle
	
	
	
 Figura 11 – NOME DAS COLUNAS NAS EXPRESSÕES
Para você criar um alias após a coluna, você deve colocar ‘AS’ e em seguida a palavra - sem espaços em branco e sem caracteres em português - que usará para ser o cabeçalho da coluna.
Para chamar a concatenação do PRIM_NOME com o ULT_NOME como NOME_COMPLETO, você deve comandar:
SELECT PRIM_NOME ||' '|| ULT_NOME AS NOME_completo
FROM EMPREGADO
	PostGreSql
	SqlServer
	Oracle
	
	
	
 Figura 12 - Retorno dos SGBD
Atenção
1. Repare que no comando o alias está com NOME em maiúsculo e completo em minúsculo. Analise agora o retorno e note que no PostGreSql o alias fica todo em minúsculo, no Oracle todo em maiúsculo e no SqlServer da forma que você digitou o alias.
2. O AS nos 3 SGBD é opcional. Se você escrever o comando sem o AS, ele funciona. Teste para ver.
 
Colocando espaço em branco no Alias
 Clique no botão acima.
Se você desejar utilizar espaço em branco no Alias, no Oracle e no PostgreSql, então deverá colocar o alias entre aspas duplas (“ “).
O comando seria:
SELECT PRIM_NOME ||' '|| ULT_NOME  "NOME completo"
FROM EMPREGADO
	PostGreSql
	Oracle
	
	
 Figura 12 - Retorno dos SGBD
Note que, agora, para os dois o nome da coluna, além de ter o espaço em branco está escrito da forma exata que digitamos o alias.
E no SqlServer?
Neste SGBD, além do alias também ser opcional, ele pode estar entre aspas duplas(“ “), apóstrofes (‘ ‘) ou colchetes ([ ]). Veja a figura 13.
	
	
	
 Figura 13 - ALIAS SQLSERVER
Sugestão: tente dar o comando de ALIAS no PòstGreSql ou no ORACLE utilizando apóstrofes ou colchetes e veja o que acontece.
Exemplo 1
Dica
Como seria o comando para mostrar os últimos nomes dos empregados com o cabeçalho Sobrenome, cujo retorno é exibido na figura 14?
 Figura 14 – Retorno do Comando.
Tente dar o comando no SGBD antes de ver a SOLUÇÃO.
CONTEÚDO SOLUÇÃO
Exemplo 2
Dica
Como seria o comando para mostrar a concatenação do ID do cliente com o seu Nome com o cabeçalho ‘Dados dos Clientes’? O Id deverá vir separado do nome por um hífen ( - ),cujo retorno é exibido na fig.15?
 Figura 15 – Retorno do Comando
Tente dar o comando no SGBD antes de ver a SOLUÇÃO.
CONTEÚDO SOLUÇÃO
Utilizando SELECT sem FROM
A cláusula SELECT, além de permitir a realização da projeção das colunas da tabela, pode ser utilizada para exibir resultados de operações aritméticas, retorno de funções ou textos.
Vejamos um exemplo no PostGreSql:
Atenção
Note que:
1. O comando primeiro exibe um texto (ALO), em seguida o resultado de uma operação aritmética (9+5) e finalmente retorna o valor da data da data/hora do sistema (FUNÇÃO NOW());
2. Não existe cláusula FROM, pois desejamos retornar apenas uma linha com os valores.
O que aconteceria se fosse acrescentada uma cláusula FROM com um nome de tabela?
Note na figura acima que retornaram 4 linhas todas iguais. Isso acontece porque tanto as expressões como a função NOW() são de linha, ou seja, retornam uma linha para cada linha da tabela da cláusula FROM. Como a tabela CLIENTE possui 4 linhas, o retorno tem essa quantidade de linhas.
Por isso é omitida a cláusula FROM, já que desejamos apenas uma linha de retorno.
E o SqlServer, como fica?
Muito Similar. A única diferença é que a função que retorna a data/hora se chama GETDATE().
Como no PostgreSql, se tiver FROM, retornará uma linha para cada linha da tabela.
Faltou o Oracle.
A função de data do Oracle é SYSDATE. Veja na figura abaixo o retorno do comando
Note que deu o erro, pois a cláusula From não foi encontrada. Por que isso acontece?
Ao contrário do PostGreSql e do SqlServer, no Oracle a cláusula FROM é obrigatória. Como fazemos então para conseguir listar os valores? Colocamos a Cláusula FROM com a tabela DUAL, conforme a figura abaixo.
Atenção
Observações:
1. Sysdate também pode retornar a hora mas temos que fazer algumas configurações que ultrapassam o nosso escopo aqui.
2. Como vimos antes no SqlServer e no PostgreSql também podemos colocar a cláusula FROM com um nome de tabela, só que retornaram uma linha para cada linha da tabela, mas como a cláusula FROM não é obrigatória não é um problema.
3. No Oracle se colocarmos uma tabela com 4 linhas na FROM retornaram 4 linhas, como a cláusula FROM é obrigatório isto poderia gerar um problema. Para eliminar esta dificuldade existe uma tabela de sistema chamada DUAl que possui uma única linha e que deverá ser colocada na cláusula FROM sempre que se desejar retornar uma única linha com expressões ou funções de linha.
Se por curiosidade você quiser saber o conteúdo de DUAL, basta comandar:
Você verá que a tabela possui uma única coluna chamada DUMMY e uma Linha com o valor X.
Atenção
Importante: DUAL é uma tabela de sistema em que nenhum usuário pode DROPAR ou INSERIR linhas, tampouco ALTERAR ou ELIMINAR sua única linha.
· LINGUAGEM SQL – SELECT – PARTE 2
Gerando restrições às consultas
Até agora, todos os comandos que demos retornaram todas as linhas da tabela. Mas e se você desejar filtrar as tabelas e retornar apenas as linhas que atendam a uma condição?
Nesse caso, você deve acrescentar a cláusula Where ao comando de Select.
Saiba mais
A cláusula Where estabelece uma condição que a linha deverá obedecer para que faça parte do conjunto resposta da consulta. No caso, apenas retornam as linhas cujo teste da condição dê como resposta verdadeiro.  
Ao selecionar os dados para visualização ou outra necessidade, podemos, além de ordená-los, restringir o espectro de visualização utilizando a cláusula Where.
Repare que, das seis linhas que a tabela possui “empregado com ID de 1 até 6”, somente retornam as três que possuem ID maior que 3 (4,5 e 6).
Na construção das condições, você pode utilizar os seguintes operadores relacionais:
=
igual
<>
diferente
<
menor que
>
maior que
>=
maior ou igual a
<=
menor ou igual a
Um cuidado que você deve tomar é com o tipo de dado que está utilizando para filtrar. No caso anterior, era um dado numérico (ID) e bastava escrevê-lo. Mas e se fosse um texto?
Veja os dados da tabela CLIENTE.
 Cliente
Você deseja o ID do cliente Ponto Quente, cujo valor é 110. O Comando seria então:
· SELECT ID
· FROM CLIENTE
· WHERE NOME = 'PONTO QUENTE'
Veja o retorno.
 Retorno do Comando.
Por que não voltou o ID do cliente,já que existe esse nome na tabela? Veja o mesmo comando no Oracle e no SqlServer.
Retorno do Comando
Repare que, no SqlServer, retornou o valor 110 e no Oracle, não. O que está acontecendo?
Alguns SGBD são case sensitive para os dados, ou seja, fazem diferenciação entre letra maiúscula e letra minúscula. . Dessa forma, temos que respeitar isso, ou a consulta poderá não retornar as linhas.
No caso do nosso banco de dados, o nome do Cliente está com a primeira letra de cada palavra em maiúsculo, portanto, temos que escrever dessa forma no comando.
· SELECT ID
· FROM CLIENTE
· WHERE NOME = 'Ponto Quente'
 Retorno do Comando.
Você pode estar pensando:
Significa, então, que eu tenho que saber como está escrito no Banco de Dados?
E se eu não souber?
E se em uma linha estiver tudo maiúsculo e na outra, tudo minúsculo? E se o banco não tiver um padrão?
Neste caso, você deve padronizar a consulta utilizando uma função que leve o valor existente no banco de dados para maiúsculo ou para minúsculo antes de fazer a comparação.
Veja os exemplos a seguir.
Retorno do Comando
Repare que:
· Nos comandos PONTO QUENTE, está em maiúsculo e foi utilizada a função UPPER para levar o conteúdo da coluna NOME para maiúsculo antes da comparação;
· UPPER atua apenas na comparação, não altera o valor do existente no banco de dados.
Veja o exemplo abaixo, onde, ao pedirmos para retornar também o nome, ele vem como está no banco de dados.
 Retorno do Comando
Dois cuidados que você deve tomar ao trabalhar com string:
· A string deve vir entre apóstrofes ‘PONTO QUENTE‘;
· Se o SGBD for case sensitive, você deve escrever o comando como os dados que estão no banco ou utilizar uma função para padronizar a forma de comparação.
Trabalhando com Datas
Ao trabalhar com datas, devemos colocá-las entre aspas simples, no formato dd/mm/aaaa, onde “dd” é o dia em dois dígitos, “mm” o mês em dois dígitos e “aaaa” é o ano em quatro digitos.
Exemplo
Mostrar sobrenome e senha dos empregados admitidos em 3/3/2009.
· SELECT ULT_NOME, DT_ADMISSAO
· FROM EMPREGADO
· WHERE DT_ADMISSAO = '3/3/2009';
Retorno do Comando
Teste também os seguintes comandos:
SELECT ULT_NOME, DT_ADMISSAO
FROM EMPREGADO
WHERE DT_ADMISSAO = '3/MAR/2009'
ou
SELECT ULT_NOME, DT_ADMISSAO
FROM EMPREGADO
WHERE DT_ADMISSAO = '3/MARÇO/2009'
SELECT ULT_NOME, DT_ADMISSAO
FROM EMPREGADO
WHERE DT_ADMISSAO = '3/MAR/09'
Saiba mais
Estes formatos também são aceitos, mas, no PostgreSql, deve-se ter um cuidado: o nome/abreviatura dos meses devem ser em inglês:
Março - March
Abr - Apr
Já o Oracle e o SqlServer dão suporte aos nomes em português.
Consultando dados com várias condições
Você pode especificar critérios complexos combinando várias condições de pesquisa.
A utilização dos operadores lógicos AND e OR permite montar expressões lógicas para filtrar as linhas. Como toda expressão lógica, o operador AND somente retorna Verdadeiro (TRUE) se ambas as condições forem verdadeiras, enquanto o operador OR somente retorna FALSO (FALSE) se as duas condições forem falsas.
Veja a tabela EMPREGADO.
Vamos supor que você deseja mostrar os empregados que tenham sido contratados após primeiro de janeiro de 2010 e que tenham salário maior que R$10.000.
O comando e o resultado estão na figura a seguir.
Comando e Retorno
Repare que a utilização do AND obriga que as duas condições sejam verdadeiras para que a linha retorne. Se tivéssemos utilizado OR, bastaria uma ser verdadeira para que a linha retornasse.
Comando e Retorno
Operadores da Linguagem SQL
A linguagem SQL possui um conjunto próprio de operadores para testar condições.
Esses operadores são:
IN CONTIDO EM (LISTA)
BETWEEN ENTRE VALORES
LIKE STRING SEMELHANTE
IS NULL Testa valores nulos
Vamos agora estudá-los mais detalhadamente.
Operador IN
O operador IN permite comparar o valor da coluna com uma lista de valores e retorna verdadeiro se, em uma determinada linha, o valor da coluna for igual a um dos valores da lista.
Exemplo
Desejamos listar os empregados que trabalham no departamento 10 ou no departamento 30. Como ficaria o comando?
SELECT *
FROM EMPREGADO
WHERE ID_DEPTO IN (10,30)
Observe o retorno na figura.
Agora, para ver os empregados que NÃO trabalham nestes departamentos, basta acrescentar NOT ao comando:
SELECT *
FROM EMPREGADO
WHERE ID_DEPTO NOT IN (10,30)
Observe o retorno na figura.
Retorno do comando
Operador Between
O operador Between And permite verificar se o valor de um campo está contido em uma faixa de valores. Por exemplo, desejamos retornar o id ult_nome e cargo dos empregados com salários entre R$8.000 e R$19.500 inclusive.
O comando seria:
SELECT *
FROM EMPREGADO
WHERE SALARIO BETWEEN 8000 AND 19500
Observe o retorno na figura.
 Retorno do comando.
 Repare que retornam os empregados com salários de R$8.000 e de R$19.500. Isso mostra que o Between cria um intervalo fechado, ou seja, os limites fazem parte dos valores aceitáveis.
Para fazer a condição inversa, basta utilizarmos Not Between.
SELECT *
FROM EMPREGADO
WHERE SALARIO BETWEEN 8000 AND 19500
Observe o retorno na figura.
Retorno do comando
Podemos utilizar Between com Datas.
Por exemplo, desejamos os empregados contratados em 2009.
O comando seria:
SELECT *
FROM EMPREGADO
WHERE DT_ADMISSAO BETWEEN '1/1/2009' AND '31/12/2009'
Observe o retorno na figura.
Retorno do comando
Operador Like
O operador Like é utilizado para fazer casamento de padrão, ou seja, procurar um conjunto de caracteres que existe em uma string.
Esta operação de comparação, para poder ser eficiente, necessita do uso de caracteres coringa, que no caso do SQL são dois:
 
% - Curinga para representar uma quantidade arbitrária de caracteres (inclusive nenhum);
_ - Curinga para indicar a existência obrigatória de um caracter naquela posição.
Exemplo
Desejamos saber os dados dos empregados com o ult_nome começado com N.
 
O comando seria:
 
SELECT *
FROM EMPREGADO
WHERE UPPER(ULT_NOME) LIKE 'N%'
Observe o retorno na figura.
 Retorno do comando.
Observações
· Repare o uso da função UPPER. Esta função leva a string para maiúsculo antes de fazer a comparação, sendo muito útil para contornar a limitação do Oracle e do Postgresql, por seremCase Sensitive. Uma outra função possível de ser utilizada é lower, que leva o texto todo para minúsculo.
· No SqlServer, você deve eliminar UPPER, já que ele não é Case Sensitive.
· Note o % depois do N informando que, após essa letra, pode existir uma quantidade arbitrária de caracteres.
Outro exemplo.
Exemplo
Desejamos saber os dados dos empregados com o ult_nome terminado com S.
O comando seria:
SELECT *
FROM EMPREGADO
WHERE UPPER(ULT_NOME) LIKE '%S'
Observe o retorno na figura.
Retorno do comando
E se você quiser retornar os PRIMEIROS NOMES dos empregados que possuem E em qualquer lugar do nome? Como seria o comando? O retorno esperado é exibido na figura.
 Retorno do comando.
 Solução.
Repare no retorno. Temos Carmen com E no meio, mas temos também Ernane que possui E no início e no final, pois o % autoriza a ter uma quantidade arbitrária de caracteres, inclusive nenhum.
Se você desejasse retornar os sobrenomes que possuem E como segunda letra, não adiantaria utilizar %. Para isso temos que informar que OBRIGATORIAMENTE deve existir uma letra antes do E, utilizando nosso outro curinga, o ‘_’.
O comando seria então:
SELECT ULT_NOME
FROM EMPREGADO
WHERE UPPER(ULT_NOME) LIKE '_E%'
Observe o retorno na figura.
 Retorno do comando.
Note que temos que ter um _ no antes do E para informar que o E é a segunda letra e que, após ela, podemos ter uma quantidade qualquer de caracteres.
Alguns cuidados:
O ‘_’ deve estar colado no ‘E’. Não pode haver espaço entre eles;
Você deve colocar um ‘_’ para cada caractere. Por exemplo, para L na terceira, o comando seria o da figura abaixo.
 Comando e retorno.
Agora, quando você deseja quem não tem R no nome, deve acrescentar o NOT antes do LIKE. Veja a figura.
 Comando e retorno.
ILIKE
Devido ao fato do PostgreSql ser Case Sensitive, nos comandos utilizamos o UPPER, porémeste SGBD possui um operador de LIKE proprietário que permite que façamos o teste sem o uso da função UPPER. É o ILIKE, ou seja, Insensitive-LIKE.
Quando o utilizamos, não precisamos nos preocupar com maiúsculas ou minúsculas. Veja a figura.
 Comando e retorno.
Operador Is Null
O operador Is Null visa determinar se, no campo, existe valor ou não (o campo é nulo).
Um valor nulo é um valor que está indisponível, não foi atribuído, é desconhecido ou inaplicável, tornando inviável usar ‘=’ no teste. Como nulo não é valor, mas sim ausência de valor, ele não pode ser igual ou diferente de qualquer outro valor. Considere a tabela CLIENTE.
Se você desejasse retornar todos os dados dos CLIENTES que não são atendidos por um vendedor, o comando seria:
SELECT *
FROM CLIENTE
WHERE VENDEDOR IS NULL
Observe o retorno na figura.
Retorno do comando.
Caso contrário, se você quisesse os que são atendidos por vendedor, utilizaria IS NOT NULL. Veja o comando e o retorno na figura.
Comando e retorno.
· LINGUAGEM SQL – Funções de Grupo
Eliminando valores duplicados (DISTINCT)
Analise o conteúdo da tabela Empregados
Observe que na tabela Empregados, RODRIGUES e UGARTE possuem o mesmo cargo. E se desejássemos ver os diferentes cargos? Se comandássemos SELECT CARGO  FROM EMPREGADO, teríamos o resultado desejado?
Em termos de dados, até poderíamos dizer que sim, que todos os cargos aparecem no resultado. Mas, em termos de facilidade para o usuário, isso é suficiente?
Imagine que a tabela tivesse milhares de linhas com dezenas de cargos diferentes.
O usuário ficaria confuso, pois teria muita dificuldade de isolar todos os cargos existentes ali. Para resolver esse tipo de caso, podemos, no comando, eliminar os valores duplicados, retornando apenas uma vez cada cargo.
Para tal, devemos acrescentar a cláusula distinct ao comando de Select. Dessa forma o comando seria:
SELECT DISTINCT CARGO 
FROM EMPREGADO
Agora conseguimos o resultado que queríamos. Observe agora o seguinte comando:
SELECT DISTINCT CARGO, ULT_NOME
FROM EMPREGADO
Note que voltaram os dois vendedores. Por que isso ocorreu se o DISTINCT continua antes do cargo? O Distinct, na realidade, filtra as linhas diferentes, não os valores da coluna. Como os dois vendedores possuem nomes diferentes, as linhas são distintas, portanto as duas retornam.
Agregando dados
Até agora todos os comandos que demos retornavam uma linha para cada linha da tabela ou uma linha para cada linha da tabela que atendesse a condição da cláusula Where. Veja os exemplos abaixo.
No primeiro comando, retornaram três linhas, o total de linhas da tabela.
No segundo comando, duas linhas, o total de linhas que atendem a condição da cláusula Where.
Observe agora os próximos dois comandos.
Note que, com os dois comandos, retornou apenas uma linha.
No primeiro, com valor três (total de linhas da tabela) e no segundo, com  valor dois (quantidade de linhas que atendem a cláusula Where).
O que mudou? Foi acrescentado COUNT na claúsula Select que, como você já deve ter percebido, contou as linhas que a consulta retornaria e exibiu esse valor. O que fizemos foi agregar dados, ou seja, derivamos um dado sumarizado a partir dos dados da tabela.
Saiba mais
Para fazer isso, você deverá utilizar as FUNÇÕES DE GRUPO, das quais COUNT é um exemplo.
Funções de grupos
Uma função de grupo atua em uma instância da tabela, ou seja, no conjunto de suas linhas.
As funções agregam os dados a partir de todas a linhas da tabela ou de grupos em que as linhas possam ser enquadradas.
A princípio, a tabela forma um único grupo, e a consulta com função de grupo retornará uma única linha.
Ao utilizarmos a cláusula GROUP BY, podemos dividir a tabela em grupo, sendo que a consulta, então, retornará uma linha para cada grupo. Na linguagem SQL, possuímos as seguintes funções de grupo:
Vejamos alguns exemplos.
Acesse o PostgreSQL e digite o seguinte comando: SELECT * FROM EMPREGADO.
Esse comando seleciona dados de todos os empregados
Vamos supor que você deseja recuperar apenas o valor médio dos salários e a soma dos salários. Para essa consulta, você comandaria: 
SELECT AVG(SALARIO), SUM(SALARIO)
FROM EMPREGADO
Atenção
Apesar de já ter sido dito, lembre-se sempre de que as funções AVG e SUM são numéricas, ou seja, exigem que os seus argumentos (colunas que passamos a função; no exemplo, a coluna SALÁRIO) sejam números.
Vejamos mais exemplos.
Agora você deseja listar o maior e o menor valor de salário de um empregado, os sobrenomes que aparecem como último e como primeiro na ordem alfabética crescente e as datas do empregado contratado há mais tempo e há menos tempo. Para isso basta comandar:
Observe que:
· Podem ser utilizadas várias funções de grupo em paralelo, na mesma coluna ou em colunas distintas;
· Quando o argumento da função é alfanumérico (como a coluna ult_nome), o valor que aparece por último na ordem alfabética crescente é o maior e o que aperece primeiro é o menor;
· Quando o argumento da função é numérico (como a coluna salário), menor e maior se referem à posição dos números no sistema de numeração, respeitado o fato de serem positivos ou negativos;
· Quando o argumento da função é data (como a coluna dt_admissao), menor e maior se referem à posição da data na linha do tempo, ou seja, a menor aparece primeiro na linha do tempo e a maior aparece por último.
Mais um exemplo:
Acesse o PostgreSql e digite o seguinte comando: SELECT * FROM EMPREGADO.
Agora você deseja saber a quantidade de empregados e a quantidade de empregados que possuem gerentes. Como seria o comando?
O comando seria:
SELECT  COUNT(*), COUNT(ID), COUNT(ID_GERENTE)
FROM EMPREGADO
E obteríamos um retorno similar ao da figura abaixo.
Observe que:
· Count(*) conta a quantidade de linhas retornadas, independentemente de seu conteúdo;
· Count(coluna) conta a quantidade de linhas não nulas naquela coluna;
· Se compararmos o resultado de count(id) com count(id_gerente), podemos notar que a primeira expressão retornou o valor 6, total de linhas da tabela já que ID é chave primária, não podendo possuir valor nulo. Já a segunda retornou 5, pois o empregado de ID 1 não possui gerente, de forma que somente cinco linhas possuem valor não nulo nesta coluna.
Se acrescentar a função de grupo DISTINCT, essa passará a ignorar os valores duplicados, computando cada um deles apenas uma vez.
Observe a figura abaixo que nos mostra o conteúdo das colunas CARGO e ID_DEPTO na tabela EMPREGADO.
Podemos observar que, na coluna cargo, dentre seis linhas há duas com o valor vendedor, e na coluna id_depto, dentre seis linhas há quatro com o valor 20.
Se desejássemos listar a quantidade de cargo e quantidade de cargos diferentes a quantidade de departamentos e a quantidade de departamentos diferentes, qual seria o comando?
O comando seria:
SELECT COUNT(CARGO), COUNT(DISTINCT CARGO),
COUNT(ID_DEPTO), COUNT( DISTINCT ID_DEPTO)
FROM EMPREGADO
Obteríamos um retorno similar ao da figura abaixo.
Observe o seguinte:
· Quando executamos o comando sem o distinct, (count(cargo) ou count(id_depto), são contadas todas as linhas não nulas;
· Quando executamos o comando com o distinct, (count(distinct cargo) ou count(distinct id_depto), cada valor discreto existente na coluna é computado apenas uma vez.
Criando grupos nas tabelas
Podemos agrupar os dados de nossa tabela utilizando a cláusula GROUP BY.
Sintaxe:
SELECT nome da coluna [ , nome da coluna]
                FROM  nome da tabela
                WHERE condição
                GROUP BY expressão
Dica
“Expressão” determina a(s) coluna(s) cujo(s) valor(es) vai servir de parâmetro para o agrupamento das linhas. Sobre os grupos criados serão aplicadas as funções de grupo, para gerar a sumarização desejada.
Por exemplo: se você desejasse saber a quantidade de empregados, a média salarial e o valor da folha salarial de cada departamento da empresa, qual seria o comando?
O comando seria:
SELECT  COUNT(*), AVG(SALARIO), SUM(SALARIO), ID_DEPTO
FROM EMPREGADO
GROUP BY ID_DEPTO
Obteríamos um retorno similar aoda figura abaixo.
Observe o seguinte:
· Na cláusula Group By, você deve colocar a coluna cujos valores serão utilizados para  criar os grupos, sendo que pertencem ao mesmo grupo todas as linhas que possuem valores iguais na coluna;
· Você também deve colocar na cláusula Select a coluna ou colunas utilizadas para criar os grupos, permitindo dessa forma que se saiba a qual grupo pertence o valor gerado pela função de grupo.
Saiba mais
No SELECT, só é permitido colocar COLUNAS que foram utilizadas no GROUP BY ou nas FUNÇÕES DE GRUPO.
Observe o exemplo da figura abaixo, similar ao comando anterior, com a diferença de que não temos a cláusula GROUP BY, gerando um erro com a presença da coluna id_depto no select.
Filtrando dados agrupados
Ao utilizar a cláusula GROUP BY, pode-se filtrar a seleção de dados antes deles serem agrupados OU/E após o agrupamento. O momento de realizar essa restrição depende do desejo de eliminar linhas da tabela antes de aplicar as funções de grupo, criando uma condição na cláusula WHERE, ou se o seu intuito é eliminar GRUPOS que não atendam a uma determinada condição, utilizando nesse caso a cláusula HAVING.
Vejamos alguns exemplos:
Você deseja filtrar a consulta por dados que existem na tabela. Por exemplo, quer contar a quantidade de empregados, o salário médio e a soma dos salários dos empregados do departamento 20. Nesse caso devemos filtrar os dados antes de agrupá-los utilizando WHERE, já que a filtragem será realizada por um dado que existe na tabela, o ID_DEPTO.
SELECT  COUNT(*), AVG(SALARIO), SUM(SALARIO)
FROM EMPREGADO
WHERE ID_DEPTO = 20
E obteríamos um retorno similar ao da figura.
Em resumo, temos que:
· Quando se deseja filtrar antes do agrupamento, utiliza-se a cláusula WHERE para eliminar as linhas da tabela que não nos interessa agrupar, de forma similar ao que fazemos no comando select, quando não desejamos que as linhas retornem no resultado da consulta;
· A condição estabelecida no WHERE, as linhas que não a atendem, no caso do exemplo as linhas que não são do ID_DEPTO 20, não retornam. Dessa forma somente as linhas do departamento 20 estarão no conjunto a ser feito com a agregação de dados;
· Após a filtragem das linhas da tabela é que os dados são agrupados e as funções aplicadas, retornando, portanto, apenas os valores referentes ao departamento desejado.
A cláusula HAVING tem função semelhante à cláusula WHERE, mas é aplicada aos resultados das funções de grupo geradas para cada grupo, não nas linhas das tabelas. Em outras palavras, após gerarmos os resultados dos grupos, podemos filtrá-los retornando apenas aqueles que atendam às condições da Cláusula HAVING.
Considere agora o seguinte comando:
SELECT  ID_DEPTO,COUNT(*), AVG(SALARIO), SUM(SALARIO)
FROM EMPREGADO
GROUP BY ID_DEPTO
Note que os departamentos 20 e 30 possuem mais de um empregado. Se desejássemos listar os departamentos que possuem mais de um empregado, como seria o comando?
A primeira ideia que poderíamos ter seria utilizar a cláusula WHERE como no seguinte comando:
SELECT  COUNT(*), AVG(SALARIO), SUM(SALARIO), ID_DEPTO
FROM EMPREGADO
WHERE COUNT(*) > 1
GROUP BY ID_DEPTO
Esse comando gera um erro, conforme podemos ver na figura abaixo:
Não podemos utilizar funções de grupo desta forma na cláusula WHERE, somente em subconsulta, como veremos mais à frente no curso. Além disso, devemos lembrar que, na tabela original, não existe a contagem de linhas e a cláusula WHERE trabalha nos dados existentes na tabela.
Qual seria o comando então? Veja na figura abaixo.
Note o uso da cláusula HAVING para criar condições às quais os grupos devem obedecer para poderem retornar. Podemos dizer que a cláusula HAVING é similar à cláusula WHERE somente se aplicada aos dados gerados pelas funções de grupo.
Observe que você pode apenas usar WHERE para restringir linhas individuais. Para restringir grupos, usa-se a cláusula HAVING.
Um comando com cláusulas WHERE e HAVING funciona obedecendo aos seguintes passos:
· Primeiro são selecionadas as linhas da tabela que satisfazem a condição da cláusula WHERE (se não houver, todas a linhas são selecionadas);
· As linhas são agrupadas;
· A função de grupo é aplicada ao Grupo;
· Os grupos que satisfazem a condição do HAVING são exibidos (se não houver, todos os grupos serão exibidos).
Ordenando consultas
Até agora, em todos os comandos que você viu, as linhas retornaram na ordem em que foram produzidas. Porém, muitas vezes, pode ser necessário que elas sejam ordenadas. Para permitir isso, o SQL possui a cláusula ORDER BY.
O resultado de uma consulta pode ser ordenado pelo valor de uma ou mais colunas, de forma crescente ou decrescente.
A sintaxe básica do ORDER By é:
SELECT { * | nome da coluna [, nome da coluna ...]}
                FROM nome da tabela
                WHERE condição {AND | OR} condição
                ORDER BY  nome da coluna  [ ASC  |  DESC ]  [, nome da coluna   [ ASC | DESC] . ]
                onde
           ASC ordena as linhas de forma ascendente; é a ordenação default.
                DESC ordena as linhas de forma descendente.
Saiba mais
A cláusula ORDER BY será sempre a última de um comando SQL.
Vejamos um exemplo: desejamos listar o ID, o sobrenome, a data de admissão, o cargo e o salário de todos os empregados em ordem crescente de salário.
Note que:
· O resultado da consulta voltou ordenado na forma solicitada. No exemplo, a ordenação definida na cláusula ORDER BY fez com que as linhas retornadas da tabela EMPREGADO sejam ordenadas por SALÁRIO e só então exibidas;
· O padrão default de ordenação da cláusula ORDER BY é crescente. Dessa forma, o uso de ASC para indicar a ordem crescente (ascendente) é opcional. Se for omitida, a ordenação ascendente será realizada, como foi o caso do exemplo.
Ordenação decrescente
Para a ordenação decrescente, basta utilizarmos a opção DESC (descendente) no lugar de ASC.
Ordenação múltipla
Podemos realizar a ordenação por várias colunas na mesma consulta. Podemos ordenar o resultado por cargo e, a partir da primeira ordenação, dentro de cada cargo por salário. Veja o exemplo abaixo.
Observe que o resultado é inicialmente ordenado pela CARGO de forma DESCENDENTE (VENDEDOR, PRESIDENTE, ETC.) e ao termos uma CARGO repetido (observe o VENDEDOR) as linhas de mesma CARGO são ordenadas entre si por SALARIO de forma ascendente.
Atenção
No comando, usamos o argumento ASC, mas como é forma padrão de ordenação, poderíamos omiti-lo.
Outra forma de comandarmos a ordenação é pela posição da coluna no resultado. Com isso o comando anterior poderia ser escrito da seguinte forma:
SELECT  *
FROM VEICULO
ORDER BY 2  ASC ,5 DESC
Onde os números 4 e 5 referenciam a quarta coluna (CARGO) e a quinta (SALÁRIO), produzindo, dessa forma, o mesmo resultado na consulta.
· Linguagem SQL – junção
Junções de tabelas
O banco de dados da EMPRESA possui, na tabela DEPARTAMENTO, os dados dos departamentos e, na tabela REGIÃO, os dados regiões.
Se você reparar no esquema da tabela DEPARTAMENTO, vai notar a existência de uma chave estrangeira (ID_REGIAO) para a tabela REGIÃO que nos permite saber a região a que o departamento pertence.
Se você deseja pegar dados dos departamentos e de sua região, por exemplo, vai utilizar a FK ID_REGIAO para ligar as linhas das duas tabelas, fazendo uma junção.
Atenção
Lembre-se que, na modelagem lógica, os relacionamentos são mapeados em chaves estrangeiras. Desta forma, fazer junção nada mais é que recuperar os dados das entidades que estão relacionadas nas duas tabelas.
Tipos de junção:
1
Junção cruzada
Retorna o produto cartesiano das duas tabelas, ou seja, a combinação de todas as linhas de uma tabela com todas as linhas de outra tabela.
2
Junção interior
Neste tipo, retornam as linhas que estão relacionadas nas duas tabelas.
3
Junção exterior
Neste tipo, retornam as linhas relacionadas e as não relacionadas em uma ou duas tabelas.
Sintaxe da junção:
Os comandos de junção interior e junção cruzada podem ser escritos de duas formas diferentes, ou seja, em duas sintaxes diferentes. Uma delasé a tradicional, mais antiga, e a segunda é a sintaxe ANSI.
Tradicional
Na cláusula from, listamos as tabelas com seus nomes separados por vírgula e, no caso da junção interior, na cláusula where deve ser escrita a condição de junção [join condition], que as linhas devem atender para participarem da resposta.
ANSI
Na cláusula from, deve ser especificado o tipo de junção que estamos realizando com a condição de junção sem ser estabelecida na subcláusula on.
Os comandos de junção exterior, na maioria do SGBDs, serão escritos na sintaxe ANSI.
Ao longo desta aula, exemplificaremos as duas sintaxes.
 Junção cruzada (cross join)
Este tipo de junção gera a combinação de todas as linhas de uma tabela com todas as linhas da outra tabela; é o chamado produto cartesiano.
 
Como a junção cruzada, combinadas todas as linhas das duas tabelas, não existe uma condição de junção.
 
Observe o conteúdo das tabelas Departamento e Região:
Se você comandar a junção cruzada das duas tabelas, o que irá acontecer?
Note que a tabela Veículo possui 10 linhas e modelo 5. O resultado final terá então 50 linhas, já que cada uma das linhas da tabela será combinada com todas as linhas de Modelo.
Na sintaxe tradicional, o comando será:
SELECT *
FROM DEPARTAMENTO, REGIÃO
Note que:
1
Retornam seis linhas.
2
Se você olhar a última coluna (nome da região primeiro), temos a região Norte, associada a todos os três departamentos, e depois Sul associada a todos os departamentos.
3
Se existissem mais regiões, o descrito no item 2 se repetiria para todas.
4
As linhas 1 e 4 são do mesmo departamento, já que é o início de um novo conjunto de linhas ligadas à mesma região.
5
Não existe condição de junção.
6
O esquema do retorno, ou seja a ordem das colunas, é a justaposição das colunas da primeira tabela da cláusula from com as da segunda. Se você inverter a ordem na cláusula from, o retorno também será invertido, como mostra a figura a seguir.
Já na sintaxe ANSI, devemos escrever na cláusula from o tipo de junção comandado.
SELECT *
FROM DEPARTAMENTO CROSS JOIN REGIAO
Observe agora o seguinte comando:
SELECT *
FROM EMPREGADO
CROSS JOIN DEPARTAMENTO
CROSS JOIN REGIAO
Ele faz o produto cartesiano das três tabelas, gerando 36 linhas (6 empregados X 3 departamentos X 2 regiões).
Em qualquer comando de junção, independentemente da sintaxe, podemos determinar as colunas que desejamos, basta listá-las no Select.
Se você desejasse retornar apenas o nome do departamento e o nome da região, poderia comandar:
SELECT NOME, NOME
FROM DEPARTAMENTO CROSS JOIN REGIAO
Correto? Não; veja o erro do comando:
Analise a mensagem de erro. Ela diz que a coluna nome é ambígua. Como assim, ambígua?
Acontece que tanto a tabela Departamento como a tabela Região têm uma coluna com o título Nome, e o SGBD não sabe qual delas utilizar no comando. A solução é qualificar a coluna, ou seja, colocar o nome da tabela seguido do nome da coluna ligados por um ponto, da seguinte forma:
Esta solução, a qualificação como o nome da tabela, pode ser trabalhosa, já que os nomes de tabela podem ter até 40 caracteres. Uma forma para resolvermos isso é apelidarmos as tabelas e usarmos este apelido para qualificarmos as colunas.
Um apelido (também chamado de alias) de tabela nada mais é que uma ou mais letras colocadas logo depois do nome da tabela na cláusula FROM.
Observe este comando e reflita:
Atenção
Depois que você cria o apelido, não pode mais utilizar o nome da tabela para qualificar as colunas.
 Junção interior (inner join)
Este tipo de junção recupera as linhas relacionadas nas tabelas envolvidas na junção.
Se você desejasse retornar os dados do departamento e os da região a que o departamento pertence, seria este tipo de junção que deveria comandar. O fato de retornarem as linhas relacionadas apenas acarreta que, se existem departamentos sem região ou região que não tem departamentos, estes não aparecem no resultado.
O Inner join é também chamado de Equijoin quando a condição de junção utiliza a igualdade, ou seja, quando o valor da coluna de uma tabela (normalmente a chave estrangeira) é igual ao valor da coluna na outra tabela (normalmente a chave primária).
Essa junção pode ser comandada tanto na sintaxe tradicional como na ANSI. Vamos estudá-las.
Junção interior – sintaxe tradicional
A sintaxe tradicional do inner join tem o seguinte formato:
 
 
 
sintaxe tradicional do inner join
select <colunas>
from tabela1, tabela2
Where <condição de junção>;
	
Condição de junção é uma expressão de comparação entre as colunas das duas tabelas envolvidas, normalmente a chave de primária de uma com a chave estrangeira da outra.
Na realidade, a sintaxe tradicional pode ser entendida como o produto cartesiano das duas tabelas seguido de uma seleção utilizando a cláusula where.
Vamos comandar a junção de Departamento e Região.
A coluna ID_REGIAO em departamento é uma FK para a tabela Região, que tem como PK a coluna ID_REGIAO. Desta forma, o comando seria:
SELECT *
FROM DEPARTAMENTO D, REGIAO R
WHERE D.ID_REGIAO = R.ID_REGIAO
Junção interior – sintaxe ANSI
Na sintaxe ANSI, junções interiores são indicadas com inner join:
 
 
 
sintaxe ANSI
select <colunas>
from tabela1 INNER JOIN tabela2 ON <condição de junção;>
	
No caso anterior, o comando seria:
SELECT *
FROM DEPARTAMENTO D
INNER JOIN REGIAO R ON D.ID_REGIAO = R.ID_REGIAO
Junção interior de mais de duas tabelas
Podemos fazer a junção de mais de duas tabelas. Para isto, basta acrescentarmos uma nova tabela com uma nova cláusula de junção.
Vejamos um exemplo inicialmente na sintaxe ANSI. A primeira coisa a fazer é identificar quais tabelas podem se juntar. Analise o modelo do banco:
Temos uma FK de Empregado para Departamento e uma FK de Departamento para Região. Desta forma, temos que comandar a junção de Empregado com Departamento, que gera uma tabela intermediária em memória, e juntar este resultado com Região.
O mesmo comando na sintaxe tradicional seria:
Neste caso, colocamos as tabelas na cláusula from e as condições de junção no where, ligadas por and.
Saiba mais
Utilizando o nosso banco de dados de exemplo, vamos fazer alguns exercícios.
· Linguagem SQL – Subconsulta e Operadores de Conjunto
Junção exterior (outer join)
Este tipo de junção retorna as linhas que estão relacionadas, como no INNER JOIN, e as não relacionadas de uma ou mais tabelas.
Vejamos um exemplo:
Exemplo
Queremos retornar todos os empregados e os clientes que eles atendem. Este comando seria um comando de junção interior normal, no qual a coluna Vendedor deve ser igualada à coluna ID de empregado. Observe que somente os empregados de ID 5 e 6 atendem algum cliente, portanto apenas eles podem retornar na consulta.
EMPREGADO
VENDEDOR = ID
CLIENTE
O comando seria então:
SELECT C.ID, C.NOME, E.ID, E.ULT_NOME, E. CARGO
FROM EMPREGADO E INNER JOIN CLIENTE C ON C.
VENDEDOR = E. ID
Resultando na tabela da figura 1, que geraria o seguinte resultado:
Figura 1: resultado do comando.
Note que no resultado voltam apenas os empregados de id 5 e 6, pois estão relacionados como clientes; os demais não aparecem no resultado (id 1, 2, 3 e 4).
E se desejássemos retornar todos os empregados e para os vendedores os dados dos clientes?
Comandaríamos então uma junção exterior. Neste caso, substituiríamos a expressão inner por left ou right caso a tabela que desejamos retornar esteja do lado esquerdo ou direito do comando.
No caso, como empregado está à esquerda, o comando seria:
SELECT C.ID, C.NOME, E.ID, E.ULT_NOME, E. CARGO
FROM EMPREGADO E LEFT JOIN CLIENTE C ON C. VENDEDOR = E. ID
Resultando na tabela da figura 2:
Figura 2: resultado do comando.
Note que as colunas de clientes ficam nulas nas linhas que correspondem aos empregados que não se relacionam com clientes.
E se o comando fosse de right join, o que aconteceria?
SELECT C. ID, C. NOME, E. ID, E. ULT_NOME, E. CARGO
FROM EMPREGADO E RIGHT JOIN CLIENTE C ON C.
VENDEDOR = E. ID
Figura 3: resultado do comando.
Retornaríamos todos os clientes e, para os que não se relacionam com vendedores (Casa Desconto),as colunas de empregado seriam nulas.
Uma terceira forma de fazer a junção exterior é com full join, conforme mostra a figura 4:
Figura 4: resultado do comando.
O full join retorna todos os relacionados e os não relacionados das duas tabelas, preenchendo com nulo as colunas da outra tabela para as linhas não relacionadas. Ou seja, é um left e um right realizados em conjunto.
Você pode estar se perguntando :
Para que serve isso? Por que eu desejaria retornar os relacionados e os não relacionados?
Normalmente isso ocorre:
1
Quando você deseja saber quais elementos de uma tabela não estão relacionados com os da outra tabela.
2
Quando você precisa fazer uma junção e necessita garantir que retornem todos os elementos de uma determinada tabela.
Vamos discutir cada um destes casos.
· Determinar os elementos não relacionados:
Para exemplificar esta situação, vamos incluir mais uma linha na tabela de Região.
INSERT INTO REGIAO VALUES (3,'Centro')
A tabela então ficaria como está na figura 5:
Figura 5: resultado do comando.
Se olharmos na tabela de Departamentos, veremos que não existe departamento ligado à região Centro (id_regiao = 3).
Figura 6: tabela departamento.
Vamos detalhar a primeira situação: quando você deseja saber quais elementos de uma tabela não estão relacionados com os da outra tabela. Portanto, se você desejasse retornar todos os dados das regiões que não têm departamentos, teria de comandar uma junção exterior.
Façamos passo a passo:
1. Fazer a junção exterior:
Primeiro, temos que determinar como fazer a junção exterior. Para isso, escrevemos o comando retornando todas as colunas das duas tabelas, conforme você pode ver na figura 7.
Figura 7: resultado do comando.
2. Isolar a região não ligada a departamentos:
Analisando o retorno (figura 7), podemos notar que a PK da tabela Departamento (coluna ID) ligada à região Centro é nula. Como vimos, isso acontece devido ao fato de a junção exterior acrescentar ao retorno uma linha toda nula nas colunas da tabela de departamento.
Desta forma, basta filtrar o resultado por esta coluna para isolar a região Centro, conforme você pode ver na figura 8:
Figura 8: resultado do comando.
3. Retornar apenas os dados da Região
Se você observar a figura 6, vai notar que estão retornando as colunas de departamento (todas nulas). Para retornarem apenas as da Região, basta fazer a projeção, conforme você pode ver na figura 9:
Figura 9: resultado do comando.
Duas observações importantes:
Note o uso do alias com o * no select (R.*). É uma forma otimizada de pedir para retornar todas as colunas de uma das tabelas, sem ter que listá-las na cláusula.
O passo a passo mostrado é meramente didático; o comando da figura 9 funciona e gera o resultado esperado.
Vejamos agora um exemplo da segunda situação:
Exemplo
Quando você precisa fazer uma junção e necessita garantir que retornem todos os elementos de uma determinada tabela. Você deseja retornar o nome da região e o do departamento que fica na região. Para regiões que não têm departamento, retornar o nome da região e o texto “não tem”.
Conforme vimos no caso anterior, a Região 3, Centro, não está ligada a nenhum departamento, portanto se fizéssemos um inner join, ela não retornaria (figura 10).
Figura 10: resultado do comando.
Teremos então que fazer um outer join. Vamos novamente passo a passo:
1. Fazer a junção exterior:
Primeiro, temos que determinar como fazer a junção exterior; para isto, escrevemos o comando retornando todas as colunas das duas tabelas, conforme você pode ver na figura 11:
Figura 11: resultado do comando.
2. Projetar as colunas desejadas:
Como desejamos apenas as colunas Nome da região e Nome do departamento, devemos fazer a sua especificação na cláusula select, conforme você pode ver na figura 12.
Figura 12: resultado do comando.
3. Substituir o nulo no nome do Departamento pela mensagem “Não tem”:
Para fazer esta substituição, vamos utilizar uma função chamada COALESCE. Se o primeiro valor nos parênteses for nulo, a função o substitui pelo segundo valor, conforme podemos ver na figura 13:
Figura 13: resultado do comando.
Duas observações importantes:
Este comando funciona exatamente da mesma forma no Oracle e no SQLServer.
O passo a passo mostrado é meramente didático; o comando da figura 13 funciona e gera o resultado esperado.
Finalmente, você pode estar se perguntando: onde está o outer no comando de junção exterior, já que em todos os comandos que demos ele não aparece, ao contrário da junção interior, na qual sempre escrevemos inner?
Na realidade, tanto inner como outer são opcionais. Na figura 14, podemos ver o comando utilizando outer, e na 15, o de inner join somente com join.
Figura 14: resultado do comando.
Figura 15: resultado do comando.
Qual seria o comando para mostrarmos uma lista de todos os gerentes, cada um com seus subordinados?
Junção exterior – sintaxe tradicional do Oracle
Ao contrário da sintaxe tradicional de inner join, que é igual em todos os SGBDs, existe no Oracle uma sintaxe de outer join proprietária cuja sintaxe tradicional é:
SELECT nome da tabela1.nome da coluna, nome da tabela2.nome da coluna ....
FROM nome da tabela1, nome da tabela2
WHERE nome da tabela1.nome da coluna (+) = nome da tabela2.nome da coluna
Onde:
(+) é o símbolo do outer join, que pode ser colocado em quaisquer dos lados da cláusula where, mas não em ambos os lados. Este símbolo deve ser colocado seguindo o nome da coluna, que pode não ter correspondente.
No caso do nosso exemplo, envolvendo clientes e vendedores, no qual desejamos retornar todos os empregados e para os vendedores os dados dos clientes, o comando na sintaxe tradicional seria:
SELECT C.ID, C.NOME, E.ID, E.ULT_NOME, E. CARGO
FROM CLIENTE C, EMPREGADO E
WHERE C. VENDEDOR (+) = E.ID
O resultado pode ser visto na figura 16 e é o equivalente a um right join na sintaxe ANSI.
Figura 16: resultado do comando.
O operador de outer join (+) não tem ligação com o lado da tabela na cláusula from.
Observe na figura 17 o comando invertendo a ordem das tabelas na from e veja que o resultado é o mesmo, equivalendo agora a um left join.
Figura 17: resultado do comando.
Na sintaxe tradicional do Oracle, não é possível fazer um full join; o comando gera erro, conforme podemos ver na figura 18:
Figura 18: resultado do comando.
 Autojunção
Uma autojunção [self join] é uma junção da tabela com ela mesma. Na tabela Empregado, por exemplo, cada empregado está subordinado a outro. A coluna 'id_gerente' indica o código do gerente do empregado (figura 19).
Figura 19: resultado do comando.
Para mostrarmos uma lista de todos os gerentes, cada um com seus subordinados, podemos comandar na sintaxe tradicional:
SELECT G.ID, G.ULT_NOME, G.CARGO, S.ID, S.ULT_NOME, S. CARGO
FROM EMPREGADO G, EMPREGADO S
WHERE S.ID_GERENTE = G.ID
Nesse caso, é obrigatório usar um apelido de tabela para distinguir as duas "cópias" da tabela que estão sendo relacionadas: 'G', no , representa uma linha da tabela Empregado, enquanto Gerente e 'S' representam outra linha, de um subordinado, que estão sendo comparadas entre si.
Podemos ver o resultado dessa consulta na figura 20:
Figura 20: resultado do comando.
Na sintaxe ANSI, o mesmo comando seria:
SELECT G.ID, G._ULT_NOME, G.CARGO, S.ID, S.ULT_NOME, S. CARGO
FROM EMPREGADO G INNER JOIN EMPREGADOS ON S.ID_GERENTE = G.ID
Obteríamos o mesmo resultado da consulta anterior. Observe a figura 21:
Figura 21: resultado do comando.
Note que na realidade a autojunção não é um tipo de comando de junção; o comando é de inner join; é uma forma de raciocinar para fazer a junção de uma tabela com ela mesma.
 Junção using
Existe uma outra terceira forma de se escrever um comando de junção interior, a junção using, mas o que vem a ser isso?
Repare que, tanto na tabela Departamento quanto na Região, temos uma coluna chamada id_regiao, FK em Departamento e PK em Região, que seria utilizada na cláusula de junção no comando (figura 22).
Figura 22: tabelas Departamento e Região.
O comando de junção normal seria o que vemos na figura

Outros materiais