Implementacao Banco Dados PDF
Implementacao Banco Dados PDF
Implementacao Banco Dados PDF
DE BANCO DE DADOS
autor
CLEBER COSTA DA FONSECA
1ª edição
SESES
rio de janeiro 2016
Conselho editorial regiane burger, roberto paes e paola gil de almeida
Todos os direitos reservados. Nenhuma parte desta obra pode ser reproduzida ou transmitida
por quaisquer meios (eletrônico ou mecânico, incluindo fotocópia e gravação) ou arquivada em
qualquer sistema ou banco de dados sem permissão escrita da Editora. Copyright seses, 2016.
isbn: 978-85-5548-297-7
Prefácio 5
1. Modelo Relacional 9
1.1 Introdução ao Modelo Relacional 11
1.1.1 Domínios, Relações, Variáveis e Valores 11
1.1.2 Regras de Integridade Relacional 12
1.1.2.1 Restrições em Domínio 14
1.1.2.2 Integridade Referencial 14
1.1.3 Álgebra Relacional 15
1.1.3.1 Operações de Seleção e Projeção 16
1.1.3.2 Operações de Conjuntos 18
1.1.3.3 Junção 21
2. Linguagem SQL 25
3. Indexação 67
4. Transações 81
7
Ao medirmos a temperatura de uma determinada localidade, e usando me-
todologias mais rígidas (medição da temperatura em uma área controlada e
tendo como referência exatamente um determinado momento) teremos um
conjunto de dados para podermos analisar melhor e obter um conhecimento
inerente a esses dados classificados. Sendo assim, podemos definir melhor:
DADOS: de uma maneira mais genérica, pode-se iniciar o estudo desse ter-
mo apresentando a definição de FERREIRA et al. (1999, p. 62) dado é o “princí-
pio em que se assenta uma discussão” ou o “elemento ou base para a formação
de um juízo”. Ainda, tomando-se um ponto de vista mais filosófico, dado é “o
que se apresenta à consciência como imediato, não construído ou não elabora-
do”, FERREIRA et al. (1999, p. 602). Essas definições são úteis para exemplificar
o termo dado e situar sua definição de um ponto de vista mais humano.
Computacionalmente falando, pode-se definir dado como um valor arma-
zenado e que por si só não quer dizer muita coisa. Uma lista de números, por
exemplo, 10, 12, 20, 21, 23, 38 não nos fornecem nenhum significado, mas por
assim dizer, são os dados obtidos e anotados de alguma forma. A partir do mo-
mento que se rotula a lista, por exemplo, IDADE: 10, 12, 20, 21, 23, 38, tem-se
a definição de METADADOS, ou seja, é o dado explicado através de um nome.
Seguindo o raciocínio, tem-se o termo informação, que quer dizer o dado
processado, isto é, o resultado do processamento dos dados 10, 12, 20, 21, 23,
38 respondendo a alguma pergunta. Por exemplo, quais as IDADES acima de 18
anos armazenadas? Após PROCESSAR os dados temos 4 idades, ou seja, 20, 21,
23, 38 anos.
Por fim, chega-se ao conhecimento, que nada mais é o que se deseja obter
com a informação. No exemplo sabe-se que são 4 idades das 6 armazenadas
acima de 18 anos. Após “processar” os dados com a pergunta, “quantas pessoas
são maiores de 18 anos” temos o “conhecimento” de 4 idades.
Resumindo:
• Dados: valor armazenado;
• Metadado: identificação do dado;
• Informação: Processamento dos dados mediante uma pergunta;
• Conhecimento: Deduções obtidas a partir das informações.
Bons estudos!
1
Modelo Relacional
1. Modelo Relacional
Após o conhecimento básico de dados e seus desdobramentos, pode-se evoluir
mais um pouco e imaginar como toda essa informação pode ser armazenada e
recuperada para se obter o conhecimento.
No princípio, essas listas de valores eram armazenadas de forma despreocu-
pada. Apenas sabia-se da existência da lista de idades, lista de temperaturas mé-
dias obtidas em determinada cidade, lista dos nomes das pessoas de uma cida-
de ou qualquer outra lista guardada em um sistema de maneira desproposital.
À medida que essas listas foram ficando complexas e volumosas, a obten-
ção da informação e conhecimento foram ficando cada vez mais complexos e
custosos, demandando tempo de processamento e obtendo-se informações de
pouca qualidade.
Com o objetivo de melhor classificar esses dados e consequentemente ob-
ter a informação o mais rápido e fidedigna possível, alguns modelos matemáti-
cos foram aplicados a esse conjunto de dados. Um deles foi o modelo com base
na Teoria Matemática dos Conjuntos e na Álgebra Relacional, chegando-se ao
Modelo de Dados Relacional. Esse modelo é uma ferramenta de modelação de
dados com o objetivo principal de, como o próprio nome diz, relacionar os da-
dos entre si.
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.
OBJETIVOS
• Conhecer os conceitos de Dominio, Relação, Variáveis e Valores no universo do Modelo
Relacional;
• Definir as regras de integridade relacional;
• Conhecer e aplicar a Álgebra Relacional.
10 • capítulo 1
1.1 Introdução ao Modelo Relacional
capítulo 1 • 11
EXEMPLO
Dom(V1): domínio de conta (atributo ou variável conta); conjunto de todos os números de conta.
Dom(Vn): domínio de agência (atributo ou variável agência); conjunto de todos os números
de agência.
Um esquema de Relação Rel, indicada por Rel(V1, V2, ..., Vn), é composta por
um nome de relação R e de um conjunto de atributos ou variáveis V1, V2, ..., Vn.
Cada valor V é o nome de um papel desempenhado por um domínio Dom. Os
índices das variáveis são também ditos, graus de relação. Para o exemplo de
agência bancária e conta bancária, tem-se uma relação de grau 2 para o esque-
ma de relação Banco.
Uma relação (ou estado da relação) r(R) é uma relação matemática de grau
n nos domínios dom(V1), dom(V2),..., dom(Vn), que é um subconjunto do pro-
duto cartesiano dos domínios que definem R: r(R) Q (dom(V1) x dom(V2) x ...
x dom(Vn)). O produto cartesiano especifica todas as possíveis combinações
de valores dos domínios subjacentes. Então, se indicamos o número total de
valores, ou cardinalidade, em um domínio D por I D I (presumindo que todos
os domínios sejam finitos), o número total de tuplas no produto cartesiano é |
dom(V1) | x I dom(V2) | x ... x I dom(Vn) | De todas essas possíveis combinações,
um estado de relação em um dado momento — estado de relação corrente —
reflete apenas as tuplas válidas que representam um estado em particular do
mundo real.
12 • capítulo 1
As regras de integridade também são conhecidas como restrições (em in-
glês, constraints).
As restrições são as normas aplicadas em colunas de dados na tabela. Estes
são utilizados para limitar o tipo de dados que pode entrar em uma tabela ou
relação. Isso garante a precisão e confiabilidade dos dados no banco de dados.
Restrições podem ser definidas a nível de coluna ou tabela. Restrições a ní-
vel de coluna são aplicadas somente a uma coluna, enquanto que restrições a
nível de tabela são aplicadas a toda a tabela.
A seguir algumas restrições disponíveis no SQL mais usadas.
• NOT NULL: Garante que a coluna não pode ter um valor NULL;
• DEFAULT: Fornece um valor padrão para uma coluna quando nenhum
é especificado;
• UNIQUE: Garante que todos os valores em uma coluna são diferentes;
• PRIMARY KEY: Identifica cada linha / registro, de maneira única, em uma
tabela de banco de dados;
• FOREIGN KEY: Identifica linhas / registros relacionada a uma ou-
tra tabela;
• CHECK: A restrição CHECK garante que todos os valores em uma coluna
satisfaçam determinadas condições;
• INDEX: Usada para criar e recuperar dados mais rapidamente.
capítulo 1 • 13
1.1.2.1 Restrições em Domínio
As Restrições de Domínio, especificam que, dentro de cada tupla, o valor de cada
atributo V deve ser um valor atômico do domínio. Por atômico entende-se que
cada valor do domínio é indivisível no que diz respeito ao modelo relacional.
Restrições de Domínio são as formas mais básicas de restrições usadas
na integridade relacional. Eles são fáceis de testar para quando os dados
são inseridos.
Os tipos de dados associados aos domínios incluem os tipos de dados nu-
méricos padrões existentes (inteiro, reais, caracteres, booleanos etc.).
EXEMPLO
Considere os seguintes atributos:
• NOME_PAI
• NOME_ALUNO
• DISCIPLINA
• NOTA
É razoável deduzir que NOME_PAI e NOME_ALUNO fazem parte de um mesmo domí-
nio. Percebe-se que para a tupla NOME_PAI, NOME_ALUNO é garantido a atomicidade de
dados, definindo-se o tipo NOME_PESSOA.
É razoável deduzir que DISCIPLINA e NOTA são partes de domínios diferentes.
14 • capítulo 1
EXEMPLO
Considere os seguintes atributos:
• NOME_ALUNO
• NOME_DISCIPLINA
• NOTA
Ao criar uma tabela para “lançar” as notas de uma disciplina de determinados alunos em
uma tabela DISCIPLINA_NOTA vemos que a Coluna ‘NOME_DISCIPLINA’, pode aparecer
várias vezes com o mesmo nome. Pode-se então, criar uma outra tabela chamada ‘DISCIPLI-
NA’ e fazer uma referência a tabela DISCIPLINA_NOTA:
DISCIPLINA_NOTA
NOME_ALUNO
NOME_DISCIPLINA
NOTA
DISCIPLINA_NOTA DISCIPLINA
NOME_ALUNO → FK_DISCIPLINA
FK_NOME_DISCIPLINA NOME_DISCIPLINA
NOTA
capítulo 1 • 15
Pode-se considerar a álgebra relacional como parte do modelo relacional
de dados dividindo-se suas operações em dois grupos principais. Um gru-
po derivado da teoria de conjuntos matemático, incluindo UNION (UNIÃO),
INTERSECTION (INTERSEÇÃO), SET DIFFERENCE (DIFERENÇA ENTRE
CONJUNTOS) e CROSS PRODUCT (PRODUTO CARTESIANO). O outro grupo,
com instruções específicas para os bancos de dados relacionais, incluindo
SELECT (SELEÇÃO), PROJECT (PROJEÇÃO) e JOIN (JUNÇÃO).
16 • capítulo 1
EXEMPLO
NOME_ALUNO NOME_DISCIPLINA NOTA
1 José Geraldo Álgebra 8
2 Eduardo Tomaz Álgebra 10
3 Cleber Dutra Álgebra 9
4 Hernesto Paula Física 10
5 Josué José Álgebra 10
Para selecionar os alunos da disciplina ‘álgebra’ cuja nota foi integral, pode-se especificar
cada uma dessas condições em uma operação de SELEÇÃO:
NOME_DISCIPLINA = ‘ALGEBRA’ AND NOTA = 10
Uma instrução SQL padrão, teremos:
SELECT * FROM DISCIPLINA_NOTA WHERE NOME_DISCIPLINA = ‘Álgebra’ AND
NOTA = 10
A álgebra relacional ficaria:
σ NOME_DISCIPLINA = ‘Álgebra’ ∧ NOTA = 10
(DISCIPLINA_NOTA)
Resultando a nova relação:
Figura 1.4 – Resultado de uma operação SELECT. Fonte: Elaborada pelo autor.
capítulo 1 • 17
EXEMPLO
Para selecionar as disciplinas e as ocorrências de notas nas disciplinas, teremos:
SELECT DISTINCT NOME_DISCIPLINA, NOTA FROM DISCIPLINA_NOTA
NOME_DISCIPLINA NOTA
1 Álgebra 8
2 Álgebra 10
3 Álgebra 9
4 Física 10
Figura 1.5 – Resultado de uma operação PROJECT. Fonte: Elaborada pelo autor.
18 • capítulo 1
EXEMPLO
Temos a tabela ALUNO e a nova tabela PROFESSOR. Podemos fazer a união dos domínios
‘NOME_PESSOA’ com os nomes dos alunos e os nomes dos professores.
Com os seguintes domínios:
NOME_PESSOA
1 Cleber Dutra
2 Elmasri
3 Fagundes Teles
4 Ferreira
5 Navathe
NOME_PESSOA
1 Cleber Dutra
2 Eduardo Tomaz
3 Fagundes Teles
4 Hernesto Paula
5 José Geraldo
6 Josué José
NOME_PESSOA
1 Cleber Dutra
2 Eduardo Tomaz
3 Elmasri
4 Fagundes Teles
5 Ferreira
6 Hernesto Paula
7 José Geraldo
8 Josué José
9 Navathe
capítulo 1 • 19
Da mesma forma como foi apresentado a operação UNION, pode-se trazer 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 res-
peito ao domínio dos atributos e ao grau da relação, também devem ser segui-
das para a operação de INTERSECTION.
Pode-se representar a operação de INTERCECAO entre as relações S e R de-
finidas acima como sendo: R S.
EXEMPLO
Para a interseção entre os nomes de professores e alunos a álgebra relacional ficaria:
NOME_PESSOA (PROFESSOR) NOME_PESSOA (ALUNO)
Resultando:
NOME_PESSOA
1 Cleber Dutra
NOME_PESSOA
1 Elmasri
2 Fagundes Teles
3 Ferreira
4 Navathe
20 • capítulo 1
Observe que as operações UNION e INTERSECTION são operações comutativas,
ou seja:
R ∪ S = S ∪ R e R ∩ S = S R.
Dessa forma, UNION e INTERSECTION, podem ser ditas operações n-nárias aplicáveis a
qualquer número de relações, pois ambas são operações associativas, isto é:
R ∪ (S ∪ T) = (R ∪ S) ∪ T e (R ∩ S) = (R ∩ S) T.
O mesmo não se pode dizer da operação MINUS, ou seja, ela não é comutativa, assim:
R – S ≠ S – R.
1.1.3.3 Junção
A operação de JUNÇÃO representado simbolicamente na álgebra relacional
pelo símbolo , definindo uma junção natural ou pelo símbolo θ, definindo
uma θ-junção ou equijunção. Para representar uma junção natural a relação
é escrita R S onde R e S são relações. O resultado de uma junção natural é
uma tabela com as combinações entre as tuplas R e S, combinadas entre si, por
meio de uma coluna com os nomes em comum.
Com a θ-junção podemos combinar tuplas de duas relações R e S, por exem-
plo, em que a ondição de combinação entre as relações não é simplesmente
uma condição de igualdade. A θ-junção pode ser descrita como: R S
aθb
onde a e b são nomes de atributos e θ é uma relação binária no conjunto {<, ≤,
=, >, ≥}.
Por exemplo, para as tabelas abaixo teremos o resultado de uma Junção na-
tural R S
PROFESSOR DISCIPLINA
1 Cleber Dutra Matemática
2 Eduardo Tomaz História
3 Fagundes Teles Ciências
capítulo 1 • 21
ALUNO DISCIPLINA
1 Cleber Dutra Historia
2 Hernesto Ciencias
3 Jonatan Matematica
4 Judas Ciencias
Resultando:
PROFESSOR IDADE_PROFESSOR
1 Cleber Dutra 20
2 Eduardo Tomaz 30
3 Fagundes Teles 40
PROFESSOR IDADE_ALUNO
1 Hernesto 16
2 Homero 35
3 Jonatan 15
4 Judas 55
22 • capítulo 1
Para a junção onde IDADE_ALUNO > IDADE_PROFESSOR, podemos representá-la por:
Resultando:
ATIVIDADES
01. Defina chave primária, chave estrangeira e qual a importância desses atributos em um
modelo relacional.
02. Na tabela abaixo, qual seria uma possível chave primária? Diga os motivos que levaram
a sua escolha.
capítulo 1 • 23
04. Em uma possível importação de dados de um arquivo do Excel, o que seria necessário
fazer, caso a chave primária de uma tabela fosse definida como sendo o CPF?
05. Por que tuplas repetidas não são permitidas em uma relação?
REFERÊNCIAS BIBLIOGRÁFICAS
[1] ELMASRI, R.; NAVATHE, S., Sistemas de Banco de Dados. Pearson Education do Brasil, 4ª.Ed
2005.
[2] PINHEIRO, Álvaro Farias, Fundamentos de Engenharia de Software: Introdução a Banco de
dados, Volume II, 5ª Ed 2015.
24 • capítulo 1
2
Linguagem SQL
2. Linguagem SQL
Com o surgimento do modelo relacional de dados, foi necessário o desenvolvi-
mento de uma linguagem adequada para a manipulação desses dados. Na dé-
cada de 70, com os estudos de Codd, um pesquisador da IBM, surgiu a lingua-
gem SQL, sigla inglesa que quer dizer Structured Query Language, traduzindo
livremente, Linguagem de Consulta Estruturada. O sucesso da linguagem foi
tamanho que obrigou o ANSI (American National Standarts Institute) a padro-
nizar a linguagem.
Em 1982, foi lançada a primeira versão oficial da SQL, outras revisões surgi-
ram: 1987, 1992, 1999 e 2003.
É uma linguagem não procedural (não depende de procedures, rotinas,
para ser executada) e bastante similar ao inglês, facilitando seu aprendizado.
O SQL pode ser dividido em 5 categorias:
• Data Definition Language (DDL): responsável pelos comandos de cria-
ção, alteração e manipulação das tabelas. Alguns comandos: CREATE, DROP,
ALTER;
• Data Manipulation Language (DML): responsável pela criação, alteração
e manutenção dos dados. Alguns comandos DML: INSERT, UPDATE, DELETE;
• Data Query Language (DQL)1: responsável pela pesquisa de dados.
Basicamente tem-se o comando SELECT;
• Data Transaction Language (DTL): responsável pela integridade de tran-
sações dos dados. Alguns comandos: SAVEPOINT, ROLLBACK, COMMIT;
• Data Control Language (DCL): responsável pela permissão e autorização
a acesso aos dados. Alguns comandos DCL: GRANT, REVOKE;
Nos parágrafos a seguir iremos estudar os principais comandos desses 5
grupos e iremos ressaltar algumas diferenças entre os principais bancos de
dados existentes (Microsoft SQL Server, Oracle SQL Server, MySQL, Postgre
e Firebird).
OBJETIVOS
• Conhecer a linguagem SQL;
• Aprender os comandos DDL (Linguagem de Definição de Dados);
• Aprender os comandos DML (Linguagem de Manipulação de Dados).
1 DQL tem apenas o comando SELECT, mas o SELECT também faz parte do grupo DML.
26 • capítulo 2
2.1 Linguagens de Definição de Dados (DDL)
EXEMPLO
Criação de uma tabela de DEPARTAMENTO com os campos NUMERO (inteiro) usado como
chave primária (valor único que vai identificar a linha da tabela), NOME (30 caracteres) e
FATOR (número com 2 casas decimais):
--SQLServer, Postgree, MySQL, Firebird e Oracle:
CREATE TABLE DEPARTAMENTO
(NUMERO INTEGER,
NOME VARCHAR(30) NOT NULL,
FATOR DECIMAL (3,2),
PRIMARY KEY (NUMERO));
capítulo 2 • 27
Essencialmente, para a criação de tabelas no MSSQL, sua sintaxe é:
CREATE TABLE
[ database_name . [ schema_name ] . | schema_name . ] table_name
[ AS FileTable ]
( { <column_definition> | <computed_column_definition>
| <column_set_definition> | [ <table_constraint> ]
| [ <table_index> ] [ ,...n ] } )
[ ON { partition_scheme_name ( partition_column_name ) | filegroup
| “default” } ]
[ { TEXTIMAGE_ON { filegroup | “default” } ]
[ FILESTREAM_ON { partition_scheme_name | filegroup
| “default” } ]
[ WITH ( <table_option> [ ,...n ] ) ]
[;]
relational_table
GLOBAL TEMPORARY SCHEMA
CREATE TABLE . TABLE objetc_table
XMLType_table
Figura 2.1 – CREATE TABLE ORACLE. Fonte: documentacao oracle, disponivel em:
<http:// docs.oracle.com/cd/B19306_01/server.102/b14200/statements_7002.htm>.
28 • capítulo 2
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
{ LIKE old_tbl_name | (LIKE old_tbl_name) }
create_definition:
col_name column_definition
| [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)
[index_option] ...
| {INDEX|KEY} [index_name] [index_type] (index_col_name,...)
[index_option] ...
| [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY]
[index_name] [index_type] (index_col_name,...)
[index_option] ...
| {FULLTEXT|SPATIAL} [INDEX|KEY] [index_name] (index_col_name,...)
[index_option] ...
| [CONSTRAINT [symbol]] FOREIGN KEY
[index_name] (index_col_name,...) reference_definition
| CHECK (expr)
Podemos concluir, que apesar de cada gerenciador de banco de dados ter
sua própria sintaxe de criação de tabelas, basicamente o comando CREATE
TABLE faz:
CREATE TABLE table_name
(column_name1 data_type(size),
column_name2 data_type(size),
column_name3 data_type(size),
....);
EXEMPLO
--SQLServer, Postgree, MySQL, Firebird e Oracle:
CREATE TABLE DEPARTAMENTO
(NUMERO INTEGER,
NOME VARCHAR(30) NOT NULL,
FATOR DECIMAL (3,2),
PRIMARY KEY (NUMERO));
capítulo 2 • 29
2.1.2 Alteração de Tabela: ALTER
Por algum motivo, após a criação de uma tabela, pode ser necessário alterá-la.
Pode-se querer criar uma coluna nova, ou alterar o tamanho dos dados armaze-
nado nessa coluna. Para isso temos o comando ALTER DATABASE.
Para adicionar uma coluna:
ALTER TABLE table_name
ADD column_name datatype
Para mudar o tipo de dados de uma coluna (no Oracle versão anterior à 10G
e MySQL):
ALTER TABLE table_name
MODIFY COLUMN column_name datatype
O comando DROP é usado para deletar TABELAS e também outros objetos (DA-
TABASE, INDEX, USER, ROLE, SCHEMA, PROCEDURE etc.).
Para deletar uma tabela:
DROP TABLE table_name
30 • capítulo 2
2.2 Linguagem de Manipulação de Dados (DML)
O comando INSERT é usado para inserir ou popular uma tabela. Sua sintaxe
básica é:
INSERT INTO table_name
VALUES (value1,value2,value3,...);
capítulo 2 • 31
2.2.2 Atualização de registros: UPDATE
A cláusula WHERE serve para restringir o efeito de uma coluna, se ela existir
a alteração somente será válida para os registros que satisfizerem a condição.
Se ela não existir todos os registros da tabela serão alterados.
Exemplos para o comando UPDATE de uma tabela nas diversas linguagens:
--SQLServer, Postgre, Oracle, MySQL, Firebird
UPDATE ALUNO
SET MATRICULA = 1,
NOME = ‘JOSUE JOSE’,
ALTURA = 1.80,
NASCIMENTO =’01/07/80’1,
APELIDO =NULL
WHERE MATRICULA = 100;
EXEMPLO
DELETE FROM PECA
1 Quando se trabalha com datas, deve-se ter cuidado ao inserir uma data como texto. Deve-se verificar qual é a
configuração de país do servidor. Na maioria das vezes é melhor inserir os dados no formato americano ‘yyyy-mm-dd’,
garantindo assim a correta armazenagem do valor.
32 • capítulo 2
Esse comando irá apagar todos os dados da tabela.
Você pode querer apagar somente um dado específico, ou parte dos dados
de uma tabela, usando o where:
DELETE FROM PECA where ID = 10
Você pode querer recuperar parte das colunas de uma tabela, especificando
cada coluna a ser exibida ou simplesmente usar o caractere asterisco (*) recupe-
rando assim todas as colunas da tabela.
SELECT * FROM table_name;
Você pode, ainda, para cada coluna recuperada usar um “alias” ou seja, re-
nomear sua coluna para a consulta ser apresentada com maior clareza.
Por exemplo, na tabela abaixo de produtos (PRODUCTS2) você pode querer
um resultado com os nomes de colunas em Português:
PRODUCTID PRODUCTNAME
1 Chai
2 Chang
3 Aniseed Syrup
4 Chef Anton's Cajun Seasoning
5 Chef Anton's Gumbo Mix
2 A tabela Products e Categories fazem parte do banco de dados NORTHWIND usado pela Microsoft para
exemplificar várias situações encontradas em um SGBD. (você poderá encontrá-lo em: https://www.microsoft.com/
en-us/download/details.aspx?id=23654. Acessado em: 20/03/2016.
capítulo 2 • 33
select ProductID as codigo,
ProductName as NomeDoProduto
from Products
O designador de “alias” AS, pode ser omitido (e na maior parte desse capítu-
lo ele o será), a consulta acima ficará:
select ProductID codigo,
ProductName NomeDoProduto
from Products
Resultando:
CODIGO NOME_DO_PRODUTO
1 Chai
2 Chang
3 Aniseed Syrup
4 Chef Anton's Cajun Seasoning
5 Chef Anton's Gumbo Mix
Você pode ainda querer deixar mais visual o nome de suas colunas resul-
tantes, deixando espaços ou até mesmo querendo usar uma palavra reservada3.
Tente fazer um SELECT tentando dar o nome da coluna usando uma palavra
reservada do SQL, por exemplo o SELECT:
select count(TIPO_PECA) AS SELECT
FROM PECA
WHERE TIPO_PECA = ‘ELETRONICO’
3 Uma palavra reservada é uma palavra que não pode ser utilizada (na maioria das linguagens de programação)
como um identificador por ser reservada para uso da gramática da linguagem.
34 • capítulo 2
select count(TIPO_PECA) AS [SELECT]
FROM PECA
WHERE TIPO_PECA = ‘ELETRONICO’
Um “ALIAS” é muito útil em consultas onde são executadas funções que to-
talizam valores, tais como SUM() e COUNT(), pois quando elas aparecem em
um SELECT se não for usado um “ALIAS” a coluna poderá ficar sem nome (no
caso do MSSQL Server) . Por exemplo:
select count(TIPO_PECA)
FROM PECA
WHERE TIPO_PECA = ‘ELETRONICO’
Resultaria:
Com “ALIAS”:
select count(TIPO_PECA) AS QUANTIDADE
FROM PECA
WHERE TIPO_PECA = ‘ELETRONICO’
QUANTIDADE
1 10
capítulo 2 • 35
Exemplo de um SELECT sem ALIAS no ORACLE:
select customerid, COUNT(*) FROM CUSTOMERS GROUP BY customerid
customerid COUNT(*)
• SAVEA 31
ERNSH 30
QUICK 28
HUNGO 19
FOLKO 19
BERGS 18
RATTC 18
Figura 2.6 – Select count(*) sem alias no oracle. Fonte: Elaborada pelo autor.
36 • capítulo 2
5 5 Grains/Cereals Breads, crackers, pasta, and cereal
6 6 Meat/Poultry Prepared meats
7 7 Produce Dried fruit and bean curd
8 8 Seafood Seaweed and fish
• =,>.>=
Select * from Categories where categoryid = 1
CategoryID CategoryName
1 1 Beverages
• Between
Select * from Categories where categoryid BETWEEN 1 AND 5
capítulo 2 • 37
• Like: Como dito, o Like é se semelhante ao =, mas possui alguns carac-
teres “curingas”, como o “%” que basicamente substitui sua posição por qual-
quer cadeia de caracteres.
Select * from Categories where CategoryName like ‘Beverages’
Semelhante a:
Select * from Categories where CategoryName = ‘Beverages’
CARACTERE
DESCRIÇÃO EXEMPLO
CURINGA
WHERE title LIKE ‘%computer%’ localiza todos os
Qualquer cadeia de zero ou
% mais caracteres.
títulos de livro com a palavra ‘computer’ em qualquer
lugar no título do livro.
WHERE au_fname LIKE ‘_ean’ localiza todos os
_ Qualquer caractere único. nomes de quatro letras que terminam com ean (Dean,
(SUBLINHADO) Sean e assim por diante).
WHERE au_lname LIKE ‘[C-P]arsen’ localiza os so-
brenomes de autores que terminem com arsen e que
Qualquer caractere único no comecem com qualquer caractere único entre C e P,
[] intervalo ([a-f]) ou conjunto por exemplo, Carsen, Larsen, Karsen e assim por dian-
([abcdef]) especificado. te. Em pesquisas de intervalo, os caracteres incluídos
no intervalo podem variar de acordo com as regras de
classificação do agrupamento.
Qualquer caractere único
WHERE au_lname LIKE ‘de[^l]%’ localiza todos os
que não esteja no intervalo
[^] (^[a-f]) ou conjunto ([^ab-
sobrenomes de autor que comecem com de e a letra
seguinte não seja l.
cdef]) especificado.
38 • capítulo 2
• In
Select * from Categories where categoryid IN (1, 2, 5, 7)
• Not
Select * from Categories where categoryid NOT IN (1, 2, 5, 7)
capítulo 2 • 39
SELECT SUM(UnitsInStock) FROM PRODUTOS
Retorna o valor 13 (soma 13 + 0)
SELECT AVG(UnitsInStock) FROM PRODUTOS
Retorna o valor 6 (média de (13 + 0) / 2). Note que se fosse levar em conta
os 3 registros, a média seria 4 (média de (13+ 0) / 3)
SELECT * FROM PRODUTOS where UnitsInStock is null
Retorna o registro de ID = 1 (onde UnitsInStock é nulo)
40 • capítulo 2
Veja as principais funções matemáticas na tabela a seguir:
capítulo 2 • 41
Um comando SELECT pode agrupar dezenas de expressões de critérios e
de novas tabelas. A combinação de critérios pode ser infinita e tão complexa
quanto se desejar, embora a complexidade vá demandar bastante tempo de
processamento do servidor. É sempre uma boa ideia mensurar essa complexi-
dade e tentar deixar os comandos SELECTs o mais enxuto possível. A seguir a
sintaxe completa do comando SELECT usada no banco de dados da Microsoft,
o Microsoft SQL Server:
<SELECT statement> ::=
[WITH <common_table_expression> [,...n]]
<query_expression>
[ ORDER BY { order_by_expression | column_position [ ASC | DESC ] }
[ ,...n ] ]
[ <FOR Clause>]
[ OPTION ( <query_hint> [ ,...n ] ) ]
<query_expression> ::=
{ <query_specification> | ( <query_expression> ) }
[ { UNION [ ALL ] | EXCEPT | INTERSECT }
<query_specification> | ( <query_expression> ) [...n ] ]
<query_specification> ::=
SELECT [ ALL | DISTINCT ]
[TOP ( expression ) [PERCENT] [ WITH TIES ] ]
< select_list >
[ INTO new_table ]
[ FROM { <table_source> } [ ,...n ] ]
[ WHERE <search_condition> ]
[ <GROUP BY> ]
[ HAVING < search_condition > ]
A cláusula FROM é uma das mais importantes, pois nela serão feitas as rela-
ções e expressões entre as entidades:
[ FROM { <table_source> } [ ,...n ] ]
<table_source> ::=
{
table_or_view_name [ [ AS ] table_alias ] [ <tablesample_clause> ]
[ WITH ( < table_hint > [ [ , ]...n ] ) ]
| rowset_function [ [ AS ] table_alias ]
42 • capítulo 2
[ ( bulk_column_alias [ ,...n ] ) ]
| user_defined_function [ [ AS ] table_alias ] ]
| OPENXML <openxml_clause>
| derived_table [ AS ] table_alias [ ( column_alias [ ,...n ] ) ]
| <joined_table>
| <pivoted_table>
| <unpivoted_table>
| @variable [ [ AS ] table_alias ]
| @variable.function_call ( expression [ ,...n ] ) [ [ AS ] table_alias ] [ (co-
lumn_alias [ ,...n ] ) ]
}
<tablesample_clause> ::=
TABLESAMPLE [SYSTEM] ( sample_number [ PERCENT | ROWS ] )
[ REPEATABLE ( repeat_seed ) ]
<joined_table> ::=
{
<table_source> <join_type> <table_source> ON <search_condition>
| <table_source> CROSS JOIN <table_source>
| left_table_source { CROSS | OUTER } APPLY right_table_source
| [ ( ] <joined_table> [ ) ]
}
<join_type> ::=
[ { INNER | { { LEFT | RIGHT | FULL } [ OUTER ] } } [ <join_hint> ] ]
JOIN
<pivoted_table> ::=
table_source PIVOT <pivot_clause> [ AS ] table_alias
<pivot_clause> ::=
( aggregate_function ( value_column [ [ , ]...n ])
FOR pivot_column
IN ( <column_list> )
)
<unpivoted_table> ::=
table_source UNPIVOT <unpivot_clause> [ AS ] table_alias
capítulo 2 • 43
<unpivot_clause> ::=
( value_column FOR pivot_column IN ( <column_list> ) )
<column_list> ::=
column_name [ ,...n ]
EXEMPLO
Na tabela PECA temos vários valores repetidos:
TIPO_PECA ID
1 ELETRONICO 1
2 ELETRONICO 2
3 ELETRONICO 3
4 ELETRONICO 4
5 ELETRONICO 5
6 ELETRONICO 6
7 ELETRONICO 7
8 ELETRONICO 8
9 ELETRONICO 9
10 ELETRONICO 10
11 OPTICO 11
12 OPTICO 12
13 OPTICO 13
44 • capítulo 2
Podemos retornar apenas os valores “distintos” para a coluna TIPO_PECA:
SELECT DISTINCT TIPO_PECA FROM PECA
TIPO_PECA
1 ELETRONICO
2 MECANICO
3 OPTICO
TIPO_PECA
1 ELETRONICO
2 ELETRONICO
3 ELETRONICO
4 ELETRONICO
5 ELETRONICO
6 ELETRONICO
7 ELETRONICO
8 ELETRONICO
9 ELETRONICO
10 ELETRONICO
Figura 2.21 – Exemplo de select usando top 10. Fonte: Elaborada pelo autor.
capítulo 2 • 45
Onde:
order_by_expression
Especifica uma coluna ou expressão na qual o conjunto de resultados da
consulta deve ser classificado. Uma coluna de classificação pode ser especifica-
da como um nome ou alias de coluna, ou um inteiro não negativo que represen-
ta a posição da coluna na lista de seleção.
Várias colunas de classificação podem ser especificadas. Os nomes de co-
luna devem ser exclusivos. A sequência das colunas de classificação na cláusu-
la ORDER BY define a organização do conjunto de resultados classificado. Ou
seja, o conjunto de resultados é classificado pela primeira coluna e então essa
lista ordenada é classificada pela segunda coluna e assim por diante.
Os nomes de coluna referenciados na cláusula ORDER BY devem corres-
ponder a uma coluna na lista de seleção ou a uma coluna definida em uma ta-
bela especificada na cláusula FROM sem nenhuma ambiguidade.
column_position
Você poderá designar a coluna a ser ordenada especificando a “posicao” da
coluna no SELECT.
EXEMPLO
Select * from Categories order by 1
Irá ordernar a consulta levando-se em conta a coluna de posição “1”, no caso a coluna
CategoryID:
Figura 2.22 – Order by usando posicao de coluna. Fonte: Elaborada pelo autor.
46 • capítulo 2
A pesquisa acima tem o mesmo efeito de:
Select * from Categories order by CategoryID
ASC | DESC
Define que os valores na coluna especificada devem ser classificados em or-
dem crescente ou decrescente. ASC classifica do valor mais baixo para o valor
mais alto. DESC classifica do valor mais alto para o valor mais baixo. ASC é a
ordem de classificação padrão. Valores nulos são tratados como os menores
valores possíveis.
EXEMPLO
Select * from Categories order by CategoryName desc
capítulo 2 • 47
SUM – retorna a soma de uma coluna;
AVG - retorna a média aritmética;
MIN - retorna o valor mínimo de uma coluna;
MAX - retorna o valor máximo de uma coluna;
COUNT - retorna a quantidade de colunas;
Por exemplo, para a tabela Categories vista anteriormente, teremos:
Select count(*) from Categories where categoryid
Irá retornar o valor 8
Select min(CategoryID) from Categories
Irá retornar o valor 1
Select sum(CategoryID) from Categories
Irá retornar o valor 36
As funções MIN, SUM, MAX não fazem muito sentidos ao serem aplicadas a
uma coluna de chave primária. Fazem mais sentido quando são aplicadas em
colunas onde podemos totalizar valores mais representativos, tais como ‘pre-
ço’, ‘data de entrega’ etc.
Por exemplo, no banco de dados NORTHIWIND temos uma tabela de “deta-
lhe de pedidos” e nela se encontram os “preços” de todos os pedidos e a “quan-
tidade” de produtos comprados, podemos querer saber qual é a média de valo-
res dos pedidos, a média de itens pedidos, a quantidade total de itens pedidos
e a média de itens pedidos:
48 • capítulo 2
select avg(UnitPrice) GastoMedioPorPedido, avg(quantity)
QuantidadeItensPorPedido, sum(unitprice) GastoTotal, sum(quantity)
QuantidadeTotal from [Order Details]
Outra cláusula bastante usada é a GROUP BY, responsável por agrupar da-
dos de uma pesquisa, seu uso é intenso quando se quer somar ou contar mem-
bros de um determinado “grupo”. Por exemplo, se quisermos saber quantos
(contar) produtos são do tipo “eletrônico” em uma tabela de componentes para
montagem de peças podemos usar:
select count(TIPO_PECA) QUANT, TIPO_PECA
FROM PECA
WHERE TIPO_PECA = ‘ELETRONICO’
GROUP BY TIPO_PECA
Repare que a pesquisa acima pode ser escrita também como:
select count(TIPO_PECA) QUANT, ‘ELETRONICO’ TIPO_PECA
FROM PECA
WHERE TIPO_PECA = ‘ELETRONICO’
Que não faz muito sentido, já que para cada tipo diferente, teríamos que
conhecer exatamente seu nome para poder criar o resultado desejado.
Mas, e se quisermos trazer a contagem de todos os tipos existentes (eletrôni-
cos, mecânicos, opticos etc.)?
Agora sim faz mais sentido usar a expressão GROUP BY, pois, ela irá retor-
nar para cada linha de tipos de matéria a sua quantidade, sem precisar especi-
ficar na sua cláusula where:
select count(TIPO_PECA) QUANT, TIPO_PECA
FROM PECA
GROUP BY TIPO_PECA
Que irá retornar:
QUANT TIPO_PECA
1 10 ELETRONICO
2 15 MECANICO
3 4 OPTICO
capítulo 2 • 49
A cláusula HAVING dá um poder a mais para o GROUP BY. Com ela pode-
mos filtrar melhor os resultados de um GROUP BY ela sempre virá após um
GROUP BY.
Se quisermos descobrir quais os tipos de peças que estão com uma contagem
baixa de estoque (com a contagem em estoque menor do que dez unidades)?
Resposta:
select count(TIPO_PECA) QUANT, TIPO_PECA
FROM PECA
GROUP BY TIPO_PECA
HAVING count(TIPO_PECA) < 10
QUANT TIPO_PECA
4 OPTICO
50 • capítulo 2
| <pivoted_table>
| <unpivoted_table>
| @variable [ [ AS ] table_alias ]
| @variable.function_call ( expression [ ,...n ] ) [ [ AS ] table_alias ] [ (co-
lumn_alias [ ,...n ] ) ]
}
<tablesample_clause> ::=
TABLESAMPLE [SYSTEM] ( sample_number [ PERCENT | ROWS ] )
[ REPEATABLE ( repeat_seed ) ]
<joined_table> ::=
{
<table_source> <join_type> <table_source> ON <search_condition>
| <table_source> CROSS JOIN <table_source>
| left_table_source { CROSS | OUTER } APPLY right_table_source
| [ ( ] <joined_table> [ ) ]
}
<join_type> ::=
[ { INNER | { { LEFT | RIGHT | FULL } [ OUTER ] } } [ <join_hint> ] ]
JOIN
4 As tabelas CATEGORIA e PRODUTO foram criadas a partir dos dados das tabelas CATEGORIES e PRODUCTS
do banco de dados exemplo da Microsoft chamado NORTHWIND (você poderá encontrá-lo em: https://www.
microsoft.com/en-us/download/details.aspx?id=23654. Acessado em: 20/03/2016.
capítulo 2 • 51
CategoryID CategoryName
1 Beverages
9 Category 1
10 Category 2
2 Condiments
3 Confections
4 Dairy Products
5 Grains/Cereals
6 Meat/Poultry
7 Produce
8 Seafood
<joined_table>
São as tabelas a serem combinadas onde serão extraídos os dados. Podem
ser usadas várias tabelas e Junções aninhados. Use parênteses para determinar
a ordem de execução das Junções.
JOIN
Indica que a operação de junção especificada serão executadas entre as ta-
belas ou visões especificadas.
ON <search_condition>
Especifica o critério de combinação ou condição de busca a ser usado entre
as tabelas, geralmente são os critérios de relacionamentos definidos entre as
tabelas. Para nossas tabelas mencionadas acima, temos:
SELECT *
FROM
CATEGORIA JOIN PRODUTO
ON
CategoryID = CategoryFK
52 • capítulo 2
explícita e deverá ser usada alguma função de conversão de conversão de tipos
(CAST ou CONVERT para o SQL, ou CAST para outras linguagens).
<join_type>
É o tipo de Junção buscada no resultado. A saber:
INNER
O parâmetro INNER especifica o retorno de apenas os dados corresponden-
tes a ambas as tabelas. Esse é o parâmetro padrão e se nada for especificado
será esse o padrão adotado pelo interpretador do SQL.
Tomando-se como exemplo nossas tabelas PRODUTO e
CATEGORIA temos:
select * from CATEGORIA INNER JOIN PRODUTO ON CategoryID =
CategoryFK
ou simplesmente:
select * from CATEGORIA JOIN PRODUTO ON CategoryID = CategoryFK
Figura 2.30 – Exemplo de junção com inner. Fonte: Elaborada pelo autor.
FULL [ OUTER ]
O parâmetro FULL especifica o retorno de todos os dados de ambas as ta-
belas independente da correspondência entre elas, as colunas que são corres-
pondentes são preenchidas, as que não são correspondentes virão preenchidas
com NULL. Para maior clareza pode vir seguido da palavra OUTER.
EXEMPLO
select * from CATEGORIA FULL OUTER JOIN PRODUTO ON CategoryID = CategoryFK
ou:
select * from CATEGORIA FULL JOIN PRODUTO ON CategoryID = CategoryFK
capítulo 2 • 53
Resultando:
LEFT [ OUTER ]
O parâmetro LEFT especifica o retorno de todos os dados da tabela à
ESQUERDA da relação além dos dados correspondentes a ambas as tabelas, as
colunas que são correspondentes são preenchidas, as que não são correspon-
dentes (à tabela da esquerda) virão preenchidas com NULL. Para maior clareza
pode vir seguido da palavra OUTER.
EXEMPLO
select * from CATEGORIA LEFT OUTER JOIN PRODUTO ON CategoryID = CategoryFK
ou:
select * from CATEGORIA LEFT JOIN PRODUTO ON CategoryID = CategoryFK
54 • capítulo 2
Resultando:
RIGHT [OUTER]
É praticamente o contrário de LEFT. O parâmetro RIGHT especifica o retor-
no de todos os dados da tabela à DIREITA da relação além dos dados correspon-
dentes a ambas as tabelas, as colunas que são correspondentes são preenchi-
das, as que não são correspondentes (à tabela da diretia) virão preenchidas com
NULL. Para maior clareza pode vir seguido da palavra OUTER.
EXEMPLO
select * from CATEGORIA RIGHT OUTER JOIN PRODUTO ON CategoryID = CategoryFK
ou select * from CATEGORIA RIGHT JOIN PRODUTO ON CategoryID = CategoryFK
Resultando:
capítulo 2 • 55
CROSS5 JOIN
Especifica o produto carteziano entre duas tabelas. Para cada linha da tabe-
la a esquerda é retornado todas as linhas da tabela a direita. Não terá a cláusula
ON para definir critérios de busca. Se a cláusula ON for especificada, um erro
de sintaxe será retornado.
EXEMPLO
select * from CATEGORIA CROSS JOIN PRODUTO
Resultando 90 linhas (9 linhas da tabela CATEGORIA X 10 linhas da tabela PRODUTO).
Abaixo apenas as primeiras linhas da operação CROSS JOIN:
Aqui, cabe ainda um parênteses sobre a cláusula JOIN. A cláusula JOIN foi introduzido
na versão SQL/92 no padrão ANSI. O ORACLE até as versões anteriores a 9i usava o pa-
drão de linguagem ANSI versão SLQ/86 que não existia o JOIN definido. Mas existe uma
forma de se obter o relacionamento entre a tabelas, que inclusive ainda é muito usado, sem
o auxílio do comando JOIN. Basta especificar a lista de tabelas na cláusula FROM e usar
as “conexões” entre as tabelas (suas chaves primárias e estrangeiras) na cláusula WHERE
fazendo uma igualdade entre as colunas chaves. Exemplificando:
5 A cláusula CROSS parece não fazer muito sentido, já que o objetivo maior em um banco de dados e retornar
dados relacionados. Mas pode ser útil na obtenção de uma “massa de dados” para ser usado durante fases de teste.
56 • capítulo 2
Para o JOIN:
select * from CATEGORIA JOIN PRODUTO ON CategoryID = CategoryFK
Podemos reescrever:
select * from CATEGORIA, PRODUTO WHERE CategoryID = CategoryFK
O resultado será o mesmo.
Podemos usar uma consulta dentro de uma outra consulta. Nesse caso a con-
sulta interna é dita “instrução-contêiner”. Por exemplo, se tivermos uma tabela
com a codificação de todos os tipos de peças, podemos retornar esses tipos por
meio de um subselect:
select TIPO_PECA TIPO, (SELECT COD_PECA FROM NATUREZA_PECA
WHERE COD_PECA = ID_PECA) CODIGO
FROM PECA
WHERE TIPO_PECA = ‘ELETRONICO’
Essa subconsulta é dita correlata, pois ela faz uma “referência” à consulta
mais externa.
Lembrando que ID_PECA está na tabela PECA e COD_PECA na tabela
NATUREZA_PECA). Para um subselect funcionar ele não pode retornar mais de
um resultado. Senão um erro será apresentado:
A subconsulta retornou mais de 1 valor. Isso não é permitido quando a sub-
consulta segue um =, !=, <, <= , >, >= ou quando ela é usada como uma expressão.
capítulo 2 • 57
Nesse caso, pode haver mais de uma relação entre ID_PECA e COD_PECA
que os dados serão retornados.
Note também, que a consulta acima pode ser escrita também da seguin-
te forma:
SELECT TIPO_PECA, COD_PECA, ID_PECA
FROM PECA, NATUREZA_PECA
WHERE ID_PECA = COD_PECA
AND TIPO_PECA = ‘ELETRONICO’
A visualização da pesquisa acima é bastante fácil e intuitiva. Então qual a
vantagem da cláusula JOIN?
A resposta está em seus argumentos LEFT, RIGHT e CROSS.
Uma subconsulta não correlata quer dizer que ela não faz referência a sua
consulta mais interna. É muito usada na cláusula WHERE como sendo um gru-
po de dados para restrição da pesquisa. Exemplo:
SELECT TIPO_PECA
FROM PECA
WHERE ID_PECA = (SELECT MAX(COD_PECA) FROM NATUREZA_PECA)
Note que a consulta interna não faz referência a nenhuma coluna da tabela
principal. Nesse tipo de pesquisa, apenas uma coluna poderá ser especificada e
ainda assim poderá trazer apenas uma linha de dados.
A pesquisa abaixo não faz sentido e retornará o erro:
SELECT TIPO_PECA
FROM PECA
WHERE ID_PECA = (SELECT COD_PECA, VALOR_NATUREZA
FROM NATUREZA_PECA)
Somente uma expressão pode ser especificada na lista de seleção quando a
subconsulta não é introduzida com EXISTS.
58 • capítulo 2
Isso acontece por que o operador igual (=) está esperando apenas um valor
para comparação. Você pode corrigir a consulta acima (mas apesar de não re-
tornar um erro isso não quer dizer que ela está “logicamente” correta) usando
o operador IN:
SELECT TIPO_PECA
FROM PECA
WHERE ID_PECA IN (SELECT COD_PECA FROM NATUREZA_PECA)
capítulo 2 • 59
CREATE FUNCTION CPF_VALIDO(@CPF VARCHAR(11))
RETURNS CHAR(1)
AS
BEGIN
DECLARE @IND INT,
@SOMA INT,
@DIG1 INT,
@DIG2 INT,
@CPF_TEMP VARCHAR(11),
@DIGIT_IGUAIS CHAR(1),
@RESULT CHAR(1)
IF @DIGIT_IGUAIS = ‘N’
BEGIN
SET @SOMA = 0
SET @IND = 1
WHILE (@IND <= 9)
BEGIN
SET @SOMA = @SOMA + CONVERT(INT,SUBSTRING(@CPF,@IND,1)) *
(11 - @IND);
SET @IND = @IND + 1
END
60 • capítulo 2
IF @DIG1 > 9
SET @DIG1 = 0;
SET @SOMA = 0
SET @IND = 1
WHILE (@IND <= 10)
BEGIN
SET @Soma = @Soma + CONVERT(INT,SUBSTRING(@CPF,@IND,1)) *
(12 - @IND);
SET @IND = @IND + 1
END
SET @DIG2 = 11 - (@SOMA % 11)
IF @DIG2 > 9
SET @DIG2 = 0;
IF (@DIG1 = SUBSTRING(@CPF,LEN(@CPF)-1,1)) AND (@DIG2 =
SUBSTRING(@CPF,LEN(@CPF),1))
SET @RESULT = ‘S’
ELSE
SET @RESULT = ‘N’
END
RETURN @RESULT
END
Se você tem uma consulta que é feita várias vezes ou a usa em diversos lo-
cais de seu sistema, você pode querer criar uma “stored procedure” com essa
consulta armazenada. Assim, se precisar alterar a pesquisa, poderá fazer em
apenas um local, não sendo necessário procurar em todo o seu sistema e ainda
correr o risco de “esquecer” algum lugar que vai chamar a consulta da maneira
antiga e retornar um erro para o usuário do sistema.
Um outro uso bastante difundido de “stored procedures” é fazer toda a ló-
gica de inserir, alterar, deletar os dados criando essas regras no próprio banco
de dados. Assim você tem um controle maior de seus dados e poderá fazer a
manutenção dessas operações em apenas um lugar.
Uma outra forma de consulta armazenada bastante usada, são as “VIEWS”
que nada mais são, do que consultas prontas para uso, e ainda podem ser usa-
das em outras consultas de maneira transparente, como sendo uma tabela
(ou entidade).
capítulo 2 • 61
Vários outros objetos são possíveis e ajudam no uso de um banco de dados.
Algum deles:
Schemas (ajudam a organizar um banco de dados), índices (melhoram as
pesquisas retornando os dados mais rapidamente), data types (tipo de dados
definidos pelo usuário), rules (regras para uso de tabelas e banco de dados),
trigger (é como uma procedure, mas são executadas logo após um update, insert
ou delete, dependendo de como são programadas). E muitos outros objetos.
62 • capítulo 2
Por exemplo:
CREATE VIEW CATEGORIA_PRODUTO
AS
SELECT CategoryID, ProductID, CategoryName, ProductName
from CATEGORIA JOIN PRODUTO
ON CategoryID = CategoryFK;
Após a criação de uma VIEW seu uso é feito como se fosse uma Tabela já
existente no Banco de dados:
SELECT * FROM CATEGORIA_PRODUTO ORDER BY CategoryName
Figura 2.35 – Resultado de um select a partir de uma view. Fonte: Elaborada pelo autor.
Uma sequência é uma maneira muito útil de definir um objeto que irá retornar
sempre um novo número que irá respeitar uma sequência pré-definida. Em al-
guns sistemas é usado para definir uma chave única, um índice de uma tabela.
Sintaxe:
CREATE SEQUENCE [schema_name . ] sequence_name
[ AS [ built_in_integer_type | user-defined_integer_type ] ]
[ START WITH <constant> ]
[ INCREMENT BY <constant> ]
[ { MINVALUE [ <constant> ] } | { NOMINVALUE } ]
[ { MAXVALUE [ <constant> ] } | { NOMAXVALUE } ]
[ CYCLE | { NOCYCLE } ]
[ { CACHE [ <constant> ] } | { NO CACHE } ]
[;]
capítulo 2 • 63
No MS SQL Server, para se definir uma coluna chave, é bastante usado o tipo
“IDENTITY” que corresponde a uma sequência de números criadas e inseridas
automaticamente em uma tabela de banco de dados.
Por exemplo, para criar uma tabela no SQL e usar um campo de auto nume-
ração para usar como chave primária usamos:
--SQLServer
CREATE TABLE CARGO(
NUMERO INTEGER IDENTITY (1,1),
NOME VARCHAR(30) NOT NULL,
PRIMARY KEY (NUMERO));
Exemplo de uso:
--SQLServer / MySQL
INSERT INTO CARGO (NOME) VALUES (‘ENGENHEIRO’)
Exemplo de uso:
--Postgree
INSERT INTO CARGO (NUMERO, NOME) VALUES
(nextval(‘CARGOSEQ’),’ENGENHEIRO’);
--Oracle
INSERT INTO CARGO (NUMERO, NOME) VALUES (CARGOSEQ.
NextVal,’ENGENHEIRO’);
Para o MySQL:
--MySQL
CREATE TABLE CARGO(
NUMERO INTEGER AUTO_INCREMENT,
NOME VARCHAR(30) NOT NULL,
PRIMARY KEY (NUMERO));
64 • capítulo 2
Exemplo de uso:
--SQLServer / MySQL
INSERT INTO CARGO (NOME) VALUES (‘ENGENHEIRO’)
ATIVIDADES
01. A relação abaixo é possível? Nela o CPF da Tabela PESSOAS está relaciona com o
CPFPAI da mesma tabela PESSOAS e o CPFMAE também está relacionado com o CPF da
mesma tabela.
PESSOAS
• CPF
NOME
CPFPAI
CPFMAE
02. Escreva uma consulta (SELECT) para retornar o Nome de uma pessoa e de seu Pai.
03. Escreva uma consulta (SELECT) para retornar o Nome de uma pessoa, seu Pai e
sua Mãe.
05. Escreva a instrução INSERT para a inserção dos seguintes dados na tabela PESSOAS:
CPF: 038.053.186-00
NOME: João
SOBRENOME: Silva
CPFPAI: NULL
CPFMAE: NULL
capítulo 2 • 65
07. Escreva a consulta abaixo sem usar o JOIN (use o WHERE). Qual você achou mais fácil
de construir? E de entender? Justifique.
SELECT * FROM Orders JOIN [Order Details] ON [Order Details].OrderID = Orders.Or-
derID JOIN Products ON Products.ProductID = [Order Details].ProductID
08. Na consulta abaixo, qual é o erro? Por que? Como você reescreveria?
SELECT sum(quantity), ProductName FROM [Order Details], Products where [Order
Details].ProductID = Products.ProductID and sum(quantity) > 10
10. A consulta a seguir está correta? O que ela faz? Como ela poderia ser reescrita?
select OrderID, (select CustomerID from Customers where customerId = orders.custo-
merId) customerId, (select [CompanyName] from Customers where customerId = orders.
customerId) [CompanyName] from orders
REFERÊNCIAS BIBLIOGRÁFICAS
[1] ELMASRI, R.; NAVATHE, S., Sistemas de Banco de Dados. Pearson Education do Brasil, 4ª.Ed
2005.
[2] PINHEIRO, Álvaro Farias, Fundamentos de Engenharia de Software: Introdução a Banco de
dados, Volume II, 5ª Ed 2015.
[3] Microsoft SQL SERVER. Documentação Microsoft SQL Server 2014, [Online]. Available: https://
msdn.microsoft.com/library/mt590198.aspx. [Acesso em 20 03 2016].
[3] ORACLE SERVER, Documentação ORACLE, [Online]. Available: http://www.oracle.com/
technetwork/pt/indexes/documentation/index.html. [Acesso em 20 03 2016].
[4] MySQL, Documentação MySQL, [Online]. Available: https://dev.MySQL.com/doc/refman/5.7/
en/. [Acesso em 20 03 2016].
[5] POSTGREE, Documentação POSTGREE , [Online]. Available: http://www.postgreSQL.org/
docs/9.5/static/index.html. [Acesso em 20 03 2016].
66 • capítulo 2
3
Indexação
3. Indexação
Uma das maiores qualidades de um Sistema Gerenciador de Banco de Dados
(SGBD) é a rapidez com que as informações são resgatadas. Essa informação,
geralmente é gravada na forma de arquivo em um disco rígido de computador.
E em um SGBD, uma pesquisa feita entre milhares de megabytes pode ser re-
tornada em questão de segundos. Na maioria das vezes não se tem a ideia da
dimensão e complexidade que o Banco de Dados atinge em um sistema. Isso
passa a ser um “mero” detalhe para quem o usa. O importante é que os dados
estão sendo retornados rapidamente e a confiança nessa informação deve ser
total. E para que essas duas qualidades sejam atendidas, rapidez e qualidade da
informação, quem constrói o banco deve se preocupar com a organização des-
sa informação. Sem isso o retorno de dados pode ser demorado e o que é pior,
pode não ter a veracidade que se espera de um banco de dados.
Uma das estruturas do Banco de Dados responsável pela rapidez nas res-
postas às pesquisas, são os índices. Eles organizam a informação de tal forma
que fica fácil e rápido encontrá-la, sobretudo levando-se em conta os milhares
de megabytes que um SBGD pode chegar. Um índice organiza os dados de uma
tabela, fazendo com que a busca por esses dados seja feita com o mínimo de
leituras, de maneira rápida e eficiente.
Esses índices são criados por meio de algoritmos eficientes de busca de da-
dos, geralmente o algoritmo usado é o B-Tree ou, Árvore B.
Uma estrutura B-Tree possui uma “raiz” (primeiro nó da árvore, por onde
sempre se iniciam as buscas), níveis intermediários e níveis folhas, conforme
figura abaixo:
RAIZ
Nível Intermediário
Nível Folha
68 • capítulo 3
Uma B-Tree sempre é simétrica, ou seja, possui os mesmos números de nós
à esquerda e à direita de cada nível.
Cada nó, em um sistema de banco de dados é uma página de dados, para
se ter uma ideia, o SQL Server da Microsoft, armazena até 8.060 bytes em
uma página.
Logicamente, não é inteligente guardar todos os dados em um nó de uma
árvore. A construção dessas estruturas é algo bastante complexa. Por isso cria-
se essa estrutura apenas para uma parte da tabela, geralmente sua chave, a essa
estrutura, dá-se o nome de ÍNDICE. Para as chaves de uma tabela, sempre são
gerados índices. Mas por algum motivo de definição de projeto, ou quando se
faz buscas constantes por determinados campos de uma tabela, pode ser inte-
ressante criar um índice específico para esses dados. É possível criar índices
primários, secundários, clusterizados, não clusterizados, XML e especiais, en-
tre outros.
OBJETIVOS
• Aprender sobre o significado e importância dos Índices;
• Conhecer e definir os tipos de Índices;
• Definir os Índices no SQL (Microsoft, Oracle, MySQL e PostgreSQL).
capítulo 3 • 69
Existem basicamente os seguintes tipos de Índices:
• Índices de nível único:
• Índices primários;
• Índices clustering;
• Índices secundários.
• Índices de múltiplos níveis;
• Índices densos;
• Índices não densos (esparso).
70 • capítulo 3
Os índices de múltiplos níveis ao contrário dos de níveis únicos, são cons-
truídos mediante a criação de vários arquivos ou vários índices em níveis. Onde
no primeiro nível a tabela é ordenada mediante a criação de um índice qual-
quer como visto anteriormente. Nos níveis seguintes, são criados índices pri-
mários sobre os índices anteriores. Pode-se construir índices multiníveis sobre
qualquer índice, seja ele primário, clustering ou secundário. O problema de
um índice de múltiplos níveis está quando é necessário excluir ou inserir um
registro. O que antes estava distribuído em arquivos balanceados, acaba fican-
do desbalanceado. A operação para reorganizar esses índices se torna bastante
complexa, já que a ordenação desses índices deve ser feita em tempo real, ou
seja, exatamente no momento que a informação é manipulada (na inserção ou
exclusão do registro).
O índice denso é constituído por um arquivo onde cada registro é indexado.
Os registros podem estar armazenados em qualquer ordem do arquivo e seu ar-
quivo de indexação consegue localizar cada registro em separado pelo arquivo
de indexação.
Um índice não denso (também chamado de índice esparso) consiste em
um arquivo de índice para blocos ou páginas do arquivo, cada um dos quais
contendo um grupo de arquivo. Esse bloco precisa estar organizado segundo
o atributo indexador. No arquivo de índice, cada índice aponta para o primeiro
registro de cada bloco.
capítulo 3 • 71
à tabela. Ordenar o índice é mais rápido que ordenar a tabela inteira, e uma
estrutura de ponteiros é definida ligando o índice ao campo da tabela, ficando
mais rápido uma busca pelo índice, que além de estar ordenado é uma estrutu-
ra menor. De maneira geral, o índice armazena o valor de cada campo da tabela
a ser ordenada e associa uma lista de ponteiros para todos os blocos de disco
que contêm registros com aquele valor de campo. Um índice primário é criado
sobre um campo chave da tabela a ser indexada. Se esse campo não é um cam-
po chave, mas é um campo onde faz-se necessário a criação de uma estrutura
para busca, esse índice é chamado índice clustering. Um índice pode ter, no
máximo, um campo de classificação física, portanto, um índice ou é primário
ou é clustering, mas não ambos. Um terceiro índice de classificação pode ser
especificado sobre qualquer outro campo da tabela que não seja o campo de
classificação da tabela, esse índice é chamado índice secundário e uma tabela
pode ter vários índices secundários além do índice de classificação primária.
72 • capítulo 3
Para localizar os funcionários pelos departamentos mais rapidamente, pode-
mos criar um arquivo de índice onde todos os departamentos são ordenados
sequencialmente e “apontar” cada departamento para os departamentos em
que cada funcionário está alocado:
DEPARTAMENTONOME FUNCIONARIONOME
COMPRAS ANA
COMPRAS EVA
COMPRAS CLARA
DESENVOLVIMENTO JUDAS
DEPARTAMENTONOME
PESQUISA PEDRO
COMPRAS
PESQUISA PATRICIA
DESENVOLVIMENTO
PESQUISA PAULO
PESQUISA
PESQUISA MARIA
RECURSOS HUMANOS
RECURSOS HUMANOS JUCA
VENDAS
RECURSOS HUMANOS JOAQUIM
VENDAS JOAO
VENDAS JOSE
VENDAS NORBERTO
capítulo 3 • 73
DEPARTAMENTONOME FUNCIONARIONOME
COMPRAS ANA
COMPRAS EVA
COMPRAS CLARA
DESENVOLVIMENTO JUDAS
DEPARTAMENTONOME
PESQUISA PEDRO
COMPRAS
PESQUISA PATRICIA
DESENVOLVIMENTO
PESQUISA PAULO
PESQUISA
PESQUISA MARIA
RECURSOS HUMANOS
RECURSOS HUMANOS JUCA
VENDAS
RECURSOS HUMANOS JOAQUIM
VENDAS JOAO
VENDAS JOSE
VENDAS NORBERTO
Um índice cluster determina a ordem em que as linhas de uma tabela (ou enti-
dade) são armazenadas no disco. Se uma tabela tem um índice cluster, no mo-
mento de uma inserção de dados os registros dessa tabela serão armazenados
em disco na mesma ordem do índice. Por exemplo, suponha que temos uma
tabela chamada “DEPARTAMENTO” que tem uma coluna de chave primária
“DEPARTAMENTO_ID” e que criamos um índice cluster para essa mesma co-
luna. Ao fazer isso, todas as linhas dentro da tabela DEPARTAMENTO serão fisi-
camente ordenadas (no disco atual em que estão inseridas) através dos valores
que estão na coluna DEPARTAMENTO_ID. Pelo fato de um índice cluster estar
associado a uma chave primária, onde só existe uma por tabela, também so-
mente um índice cluster é permitido por tabela.
Isso implicará em um ganho enorme na performance das pesquisas, pois
as colunas da tabela (ou entidade) estarão ordenadas na mesma ordem dos
74 • capítulo 3
índices clusterizados por intermédio do modelo de armazenamento usado por
esse tipo de índice. Já os índices não-cluster não fazem esse trabalho de orde-
nação dos dados tal qual é feito com os índices clusterizados. Ou seja, enquan-
to os índices clusterizados ordenam fisicamente tanto as linhas da tabela (ou
entidade) quanto os próprios índices e mantêm os mesmos próximos uns aos
outros; os não-clusterizados ordenam somente o índice em si, e não as linhas
(que são salvas de forma aleatória no disco).
Numa tabela, quando é definida uma chave primária, um índice cluster é
criado automaticamente pelo banco para essa tabela. E o que ele faz basica-
mente é ordenar as informações pela coluna de chave daquele índice em disco.
Com a criação de um índice cluster em uma tabela (ou entidade), os dados des-
sa tabela seriam sempre ordenados fisicamente seguindo a ordenação do campo
chave. E sempre que um novo dado de registro fosse inserido ou atualizado, toda
a tabela seria reorganizada para manter a ordenação correta. Essa abordagem faz
mais sentido com dados que não se alteram com frequência, por exemplo, uma
tabela de CEPs. Onde os CEPs raramente mudam ou são criados. Os índices não
clusterizados, já fazem sentido onde as informações são constantemente atuali-
zadas ou inseridas. E pelo fato de um índice não clusterizado não estar associado
a apenas um campo (chave primária) ele pode ser criado para cada coluna que se
deseja ordenar. Os índices não cluster são muito usados quando necessitamos
encontrar uma informação de várias formas diferentes como por exemplo, que-
remos encontrar um livro pelos campos Nome, Autor, Editora, Assunto etc.
Um índice Multinível pode ser definido como um índice de índices, são cons-
truídos mediante a criação de vários índices em níveis. No primeiro nível é
armazenado um “range” de valores e um ponteiro para cada chave em um se-
gundo nível, esse segundo nível possui uma parte das chaves e um novo pon-
teiro para o acesso à informação propriamente dita. Isso facilita a busca já que
é necessária uma quantidade menor de iterações de busca quando os índices
são quebrados em níveis. Esse tipo de índice se mostra mais complexo, prin-
cipalmente para a manutenção de entrada e exclusão de dados, já que ele pre-
cisa ficar organizado em diversos arquivos mantendo os “ranges” de valores
balanceados. Uma solução pode ser deixar espaços previamente alocados para
efetuar as inclusões e exclusões, para não ter que ordenar todos os arquivos de
índices novamente.
capítulo 3 • 75
Exemplo de uma estrutura de índices em dois níveis:
PK PT
40
39
38
PK INFO
40
35
PK PT PK PT
34
40 30
30
30 29
25
20 28
24
20
15
PK PT
20
19
18
76 • capítulo 3
TIPO DE ÍNDICE DESCRIÇÃO
Um índice cluster armazena as linhas de dados da tabela ou exibição em
ordem com base na chave de índice de cluster. O índice de cluster é imple-
CLUSTERED mentado como uma estrutura de índice B-tree que suporta a recuperação
rápida das linhas, com base em seus valores de chave de índice de cluster.
Um índice não cluster pode ser definido em uma tabela ou exibição com
um índice de cluster ou em um heap. Cada linha de índice no índice não
cluster contém o valor de chave não cluster e um localizador de linha. Este
localizador aponta para a linha de dados no índice clusterizado ou heap
NONCLUSTERED tendo o valor da chave. As linhas no índice são armazenadas na ordem dos
valores de índice de chave, mas as linhas de dados não são garantidas
para estar em qualquer ordem particular, a menos que um índice de cluster
é criado na tabela.
Um índice Unique garante que a chave de índice não contém valores
duplicados e, portanto, todas as linhas na tabela ou exibição é, de alguma
forma única.
UNIQUE
Uniqueness pode ser uma propriedade de ambos os índices clusterizados
e não clusterizados.
ÍNDICE COM COLUNAS Um índice agrupado que é estendido para incluir colunas não-chave para
INCLUÍDAS além das colunas de chave.
ÍNDICE EM COLUNAS Um índice em uma coluna que é derivado a partir do valor de uma ou mais
COMPUTADAS colunas, ou certas entradas determinísticas.
capítulo 3 • 77
No SQL Oracle temos:
No MySQL:
78 • capítulo 3
ATIVIDADES
01. Em sua opinião, qual a importância na criação de índices em um sistema de banco
de dados?
REFERÊNCIAS BIBLIOGRÁFICAS
[1] TENEMBAUM, Aaron - Estruturas de Dados Usando C - Ed. Person Makron Books – 2004.
[2] ELMASRI, R.; NAVATHE, S., Sistemas de Banco de Dados. Pearson Education do Brasil, 4ª.Ed
2005.
[3] PINHEIRO, Álvaro Farias, Fundamentos de Engenharia de Software: Introdução a Banco de
dados, Volume II, 5ª Ed 2015.
[4] Microsoft SQL SERVER. Documentação Microsoft SQL Server 2014, [Online]. Available: https://
msdn.microsoft.com/library/mt590198.aspx. [Acesso em 20 03 2016].
[5] ORACLE SERVER, Documentação ORACLE, [Online]. Available: http://www.oracle.com/
technetwork/pt/indexes/documentation/index.html. [Acesso em 20 03 2016].
[6] MYSQL, Documentação MYSQL, [Online]. Available: https://dev.mySQL.com/doc/refman/5.7/
en/. [Acesso em 20 03 2016].
[7] POSTGREE, Documentação POSTGREE , [Online]. Available: http://www.postgreSQL.org/
docs/9.5/static/index.html. [Acesso em 20 03 2016].
capítulo 3 • 79
80 • capítulo 3
4
Transações
4. Transações
Poder guardar milhares e milhares de informação e fazê-la de forma organi-
zada é uma das grandes vantagens de um Sistema de Banco de Dados (SGBD).
Mas como saber se toda essa informação é realmente confiável? Como saber se
todas as contas que um banco de dados é capaz de fazer, estão sendo feitas de
maneira correta, sendo arquivada junto a alguma informação que faça sentido?
Imagine se todas as transações bancárias não pudessem ser confiáveis? Se ao
criar um novo registro, ao tentar recuperá-lo descobríssemos que a informação
que deveria estar lá está fazendo parte de outro registro? Todas essas respostas
são dadas pelo sistema de “transações” de um Banco de Dados. É com ele que
garantimos que um registro de banco de dados está sendo guardado no lugar
certo, junto com as informações certas. Ele é capaz de “guiar” toda a forma que
as informações são salvas.
Sistemas de transação são sistemas desenvolvidos para bancos de dados
que garantem a execução de processamento de registros concorrentes no ban-
co de dados. Neste capítulo apresentaremos os conceitos de processamentos
de transações.
Veremos como uma transação deve ser completa e integral para garantir
precisão. Analisaremos o problema das “concorrências” que surgem quando
diversas transações, submetidas por vários usuários, interferirem nas outras,
produzindo resultados imprecisos. Veremos também como é possível recupe-
rar uma informação, caso uma transação não seja feito da maneira esperada.
OBJETIVOS
• Definir e conhecer o significado de Transacoes em Bancos de dados;
• Conhecer os estados das Transações;
• Definir as propriedades ACID.
82 • capítulo 4
4.1 Conceito de Transação
Um dos conceitos mais simples e que define muito bem o conceito de transa-
ção é o dado por “ELMASRI, R.; NAVATHE, S., Sistemas de Banco de Dados –
pag. 402”: “Uma transação é uma unidade atômica de trabalho que ou estará
completa ou não foi realizada”. Simples assim, uma transação é algo que dá a
garantia de ter ocorrido de maneira satisfatória e completa.
Uma transação inclui uma ou mais operações de acesso ao banco de dados.
Podem incluir operações de inserção, alteração, exclusão ou recuperação. Uma
operação de transação pode estar definida em um programa de aplicação ou
pode ser definida e executada mediante instruções especificas da linguagem
de banco de dados, tal como o SQL. A linguagem SQL, por meio de comandos
de início e fim podem estabelecer explicitamente as operações a serem execu-
tadas garantindo-se uma transação. Todos os comandos de acesso a dados pre-
sentes entre esse início e fim são considerados parte da transação.
capítulo 4 • 83
• ROLLBACK (ou ABORT): Indica que uma transação não terminou com
sucesso, de forma que quaisquer mudanças ou efeitos que a transação possa
ter aplicado ao banco de dados deverão ser desfeitas. Uma transação entra em
estado ativo imediatamente após o início de sua execução, no qual poderá emi-
tir operações READ (leitura) e WRITE (gravação). Quando a transação termina,
ela passa para o estado de efetivação parcial. Nesse ponto, alguns protocolos
de restauração precisam garantir que uma falha de sistema não impossibilite
a gravação permanente das mudanças promovidas pela transação (geralmente
pela gravação de mudanças no log do sistema, que será visto na próxima seção).
Uma vez atendidas todas as verificações, diz-se que a transação alcançou seu
ponto de efetivação, e entra, então, no estado de efetivação (committed state).
Uma vez efetivada, a transação tem sua execução concluída com sucesso, todas
as suas mudanças serão gravadas permanentemente no banco de dados.
Begin
transaction
End
transaction Commit
Ativa Parcialmente
Validada
(Read, Write) validada
Rollback
Invalidada Finalizada
84 • capítulo 4
regras de integridade dos dados, suas chaves e tipos de dados. Deve ser “Iso-
lada”, ou seja, o trabalho naquele registro, pertinente a aquela transação deve
ser único, sem a interferência de nenhuma outra transação ou operação que
possa estar ocorrendo. Deve ser “Durável”, uma vez executada e finalizada, seus
dados devem ser persistentes independente de qualquer ocorrência externa,
tais como uma queda de energia ou interrupção abrupta do sistema. Uma vez
finalizada seu resultado será confiável.
EXEMPLO
• Atomicidade
Ou todo o trabalho é feito, ou nada é feito.
Em uma transferência de valores entre contas bancárias, é necessário que, da conta
origem seja retirado um valor X e na conta destino seja somado o mesmo valor X. As duas
operações devem ser completadas sem que qualquer erro aconteça, caso contrário todas as
alterações feitas nessa operação de transferência devem ser desfeitas;
• Consistência
Deve respeitar as regras de chaves e tipos de dados.
Considere um banco de dados que guarde informações de produtos e que use o Código
de Barras como chave primária, no formato de 11 dígitos numéricos. Então, qualquer inser-
ção ou alteração no banco não pode duplicar um código de barras (unicidade de chaves)
ou colocar um valor de código de barras inválido, como o valor 12356789AB (restrição de
integridade lógica).
• Isolamento
Evita que transações paralelas interfiram umas nas outras.
Considere as duas seguintes transações efetuadas em um banco de dados com informa-
ções de funcionários de uma empresa (o exemplo a seguir é baseado no exemplo disponível
no wikipedia. Disponível em: <https://pt.wikipedia.org/wiki/ACID>. Acessado em 22 abr.
2016):
T_1: Aumentar o preço de um produto em 10 reais para o produto de código de bar-
ras 12345678901.
T_2: Aumentar o preço de um produto em 10% para o produto de código de bar-
ras 12345678901.
capítulo 4 • 85
Podemos visualizar as transações da seguinte forma:
T_1:
seleciona produto que tenha Código de Barras igual à 12345678901;
altera o valor somando 100 reais;
faz o commit (confirma a gravação no banco de dados).
T_2:
seleciona funcionário que tenha Código de Barras igual à 12345678901;
altera o valor somando 10%;
faz o commit (confirma a gravação no banco de dados).
Se as duas transações forem executadas sequencialmente, o preço final do produto
deve ser (o produto tem valor inicial de 1000 reais):
T_1 e depois T_2: valor passa a ser 1100 reais e depois, somando 10% de 1100, passa
a ser 1210 reais.
T_2 e depois T_1: valor passa a ser 1100 reais e depois, somando 100 reais, passa a
ser 1200 reais.
Então, se executarmos estas duas transações em paralelo, o valor final do preço desse
produto deve ser de 1200 ou de 1210 reais.
Se as duas transações não estiverem isoladas (uma puder ver os resultados parciais da
outra), então, quando executadas em paralelo, pode ocorrer o seguinte:
T_1 seleciona o produto;
T_2 seleciona o mesmo produto;
T_1 altera o preço para 1100 reais;
T_2 altera também o preço para 1100 reais;
T_1 grava a mudança no banco de dados;
T_2 também grava a mudança no banco de dados.
Assim, no fim, o preço deste produto será igual à 1100 reais (valor gravado por T_2). Isto
ocorreu neste exemplo porque deixamos as duas transações alterarem o mesmo campo (o
preço) ao mesmo tempo. A propriedade de isolamento não permite que isto ocorra.
• Durabilidade
Os efeitos de uma transação em caso de sucesso (commit) devem persistir no banco de
dados mesmo em casos de quedas de energia, travamentos ou erros. Garante que os dados
estarão disponíveis em definitivo.
86 • capítulo 4
4.4 Execução Concorrente de Transações
Vimos nos itens anteriores que uma transação ocorre mediante alguns cui-
dados que devem ser tomados pelo sistema de banco de dados. Esses passos
garantem que as propriedades “ACID” são presentes em uma transação. Além
disso, essas transações ocorrem a todo tempo em um sistema de banco de da-
dos. Mesmo as operações simples de leitura e escrita estão correndo a todo mo-
mento no sistema. Quando transações manipulam dados concorrentemente,
alguns problemas podem ocorrer tais como acesso inconsistente a dados, per-
das de atualização e perda da consistência do banco.
A maioria dessas técnicas assegura a serialização de planos de execução,
ou seja, garante que as instruções são executadas uma após a outra, sem exe-
cuções simultâneas, usando algumas regras que garantem a serialização. Um
importante conjunto de protocolos emprega a técnica de bloqueio dos itens de
dados para impedir que múltiplas transações acessem os itens concorrente-
mente. Protocolos de bloqueio são usados na maioria dos Sistemas de Bancos
de Dados comerciais. Um outro conjunto de protocolos de controle de concor-
rência usa timestamps (marcas de tempo). Um timestamp é um identificador
único para cada transação, gerado pelo sistema. Outro protocolo de bloqueio
é conhecido como protocolo de controle de concorrência de multiversão, que
usam múltiplas versões de um item de dado. Temos também um protocolo ba-
seado no conceito de validação ou certificação de uma transação depois que
ela executa suas operações; estes são, às vezes, chamados protocolos otimistas.
Um outro fator que afeta o controle de concorrência é a granularidade dos itens
de dados — isto é, qual porção do banco de dados um item de dado representa.
Um item pode ser tão pequeno quanto o valor de um único atributo (campo)
ou tão grande quanto um bloco de disco, ou todo um arquivo, ou um banco de
dados inteiro.
As técnicas de bloqueio usadas para o controle de concorrência são basea-
das no conceito de bloqueio de itens de dados, ou LOCK. Um bloqueio (LOCK) é
um controle associado a um item de dados que descreve a condição do item em
relação às possíveis operações que podem ser aplicadas a esse dado.
capítulo 4 • 87
bloqueio para cada item de dado no banco de dados e eles são usados como
meio de sincronizar o acesso por transações concorrentes aos itens do banco de
dados. Ao contrário de uma transação, um bloqueio não garante um processo
de manipulação de dados de maneira consistente. Um bloqueio apenas impede
que outros recursos acessem a tabela em LOCK. Por esse motivo o uso delibe-
rado do LOCK deve ser ponderado pois podem ocorrer DEADLOCKS (impasse)
ou STARVATION (inanição). Um deadlock ocorre quando um objeto bloqueado
está esperando algum outro recurso que também está em bloqueio e, por con-
seguinte, esse mesmo processo está esperando o primeiro que também está na
condição de bloqueio. Já a condição de starvation ou inanição ocorre quando
um processo em bloqueio não pode continuar por um período indefinido de
tempo, enquanto outras transações no sistema continuam normalmente.
88 • capítulo 4
EXEMPLO
@@ERROR:
BEGIN TRANSACTION
UPDATE FUNCIONARIO
SET SALARIO = SALARIO * 1.10
WHERE SALARIO = 1000
IF @@ERROR = 0
COMMIT
ELSE
ROLLBACK
END
Nesse exemplo estamos dando um aumento de salário de 10% para todos os funcioná-
rios cujo salário é mil reais. Caso algum erro ocorra, o comando é revertido, caso não tenha
erro, toda operação é validada.
Se ocorrer algum erro, uma mensagem do sistema será apresentada, às vezes essas
mensagens são um tanto complicadas e geralmente apresentadas na linguagem de instala-
ção do banco de dados, dessa forma, podemos fazer o uso de uma função no SQL respon-
sável por “gerar” um erro com as características definidas pelo administrador o programador
da rotina.
Ficando assim:
BEGIN TRANSACTION
UPDATE FUNCIONARIO
SET SALARIO = SALARIO * 1.10
WHERE SALARIO = 1000
IF @@ERROR = 0
COMMIT
ELSE
RAISERROR(5001,16,1,’ERRO AO ALTERAR SALARIO, TABELA FUNCIONARIO!’)
ROLLBACK
END
capítulo 4 • 89
Nessa melhoria de código, ao ocorrer algum problema na atualização do salário uma
mensagem amigável de erro será apresentada.
Nem sempre, um rollback em execuções serão feitos somente com a ocorrência de erro.
Podemos ter uma situação lógica em uma transação que provoque um rollback. Dessa forma
uma RAISEERROR pode intimidar o usuário, fazendo com que ele ache que ocorreu um erro
“catastrófico”. Para isso, podemos fazer o uso de uma propriedade PRINT, ou até mesmo
apresentar um SELECT amigável:
BEGIN TRANSACTION
UPDATE FUNCIONARIO
SET SALARIO = SALARIO * 1.10
WHERE SALARIO = 1000
IF @@ERROR = 0
COMMIT
ELSE
PRINT ‘NAO FOI POSSIVEL ALTERAR O SALARIO, TABELA FUNCIONARIO!’
ROLLBACK
END
Essa transação é dita ‘explicita’, pois requer que o comando BEGIN TRANSACTION seja
executado para termos uma transação em andamento. Esse é o modo padrão com que o
Microsoft SQL Server é executado. Mas, podemos fazer com que todas as operações sejam
executadas mediante as regras de transação. Para isso basta executar o comando abaixo
uma vez, e assim, todas as execuções desse ponto em diante serão tratadas como sendo
uma transação. Perceba que não mais será necessário a execução de um begin transaction,
mas o programador do banco de dados deverá executar o COMMIT ou ROLLBACK quan-
do necessário.
SET IMPLICIT_TRANSACTIONS ON
UPDATE FUNCIONARIO
SET SALARIO = SALARIO * 1.10
WHERE SALARIO = 1000
IF @@ERROR = 0
COMMIT
ELSE
90 • capítulo 4
PRINT ‘NAO FOI POSSIVEL ALTERAR O SALARIO, TABELA FUNCIONARIO!’
ROLLBACK
END
capítulo 4 • 91
INSERT INTO tabela1 VALUES (3);
SELECT * FROM tabela1;
COMMIT;
Ainda, no sistema de banco de dados do POSTGRE e MYSQL (no ORACLE não) existe
um comando caso o programador queira liberar um SAVE POINT. O comando é o RELEASE
SAVEPOINT esse comando irá destruir o SAVEPOINT previamente criado:
BEGIN;
CREATE TEMPORARY TABLE tabela1 (col1 int) ON COMMIT DROP;
INSERT INTO tabela1 VALUES (3);
SAVEPOINT meu_ponto_de_salvamento;
INSERT INTO tabela1 VALUES (4);
RELEASE SAVEPOINT meu_ponto_de_salvamento;
SELECT * FROM tabela1;
COMMIT;
col1
------
3
4
(2 linhas)
A transação acima inseriu tanto o 3 quanto o 4.
ATIVIDADES
01. O que é execução concorrente de transações em banco de dados num sistema multiu-
suário? Em sua opinião, por que o controle de concorrência é necessário?
92 • capítulo 4
03. O controle de transação no exemplo abaixo é necessário, por quê?
begin tran
update PESSOAS set nome = ‘ERNERSTINO’ where CPF = ‘665.854.455-70’
commit tran
04. Considere:
I. Se uma transação é concluída com sucesso (operação commit bem sucedida), então
seus efeitos são persistentes.
II. Ou todas as ações da transação acontecem, ou nenhuma delas acontece.
REFERÊNCIAS BIBLIOGRÁFICAS
[1] TENEMBAUM, Aaron - Estruturas de Dados Usando C - Ed. Person Makron Books – 2004.
[2] ELMASRI, R.; NAVATHE, S., Sistemas de Banco de Dados. Pearson Education do Brasil, 4ª.Ed
2005.
[3] PINHEIRO, Álvaro Farias, Fundamentos de Engenharia de Software: Introdução a Banco de
dados, Volume II, 5ª Ed 2015.
[4] Definicção das propriedades ACID, Wikipédia. Disponivel em: https://pt.wikipedia.org/wiki/
ACID. Acessado em: 22/04/2016.
capítulo 4 • 93
94 • capítulo 4
5
Otimização e
Processamento de
Consultas
5. Otimização e Processamento de Consultas
Neste capítulo veremos as técnicas utilizadas por um SGBD para processar,
otimizar e executar consultas de alto nível. As pesquisas feitas usando-se lin-
guagem SQL, ou QUERYs, em geral são traduzidas em uma linguagem da álge-
bra relacional e otimizadas para terem um tempo de processamento aceitável
quando executadas.
Essas etapas de tradução e otimização são feitas pelo gerenciador de banco
de dados. Encontrar um equilíbrio entre elas é uma tarefa que requer bastante
processamento e algoritmos eficientes.
Existem diferentes algoritmos responsáveis pela otimização e tradução
para implementar o acesso eficiente aos dados de um gerenciador de banco
de dados (SGBD). Esses algoritmos criam um plano de execução levando-se
em conta não somente a melhor estratégia, mas devem procurar a estratégia
mais eficiente.
As consultas escritas na linguagem SQL são lidas pelo gerenciador de ban-
co de dados (SGBD), analisadas e validadas. São usadas técnicas conhecidas da
teoria de compiladores passando por análises e sínteses. A consulta é analisada
sintaticamente então é validada e depois traduzida para uma expressão em ál-
gebra relacional e logo em seguida é otimizada pelo otimizador de consultas.
O algoritmo usado pelo SGBD busca essencialmente a tradução da consulta es-
crita em SQL para um código otimizado onde o custo de acesso aos dados será
o menor possível.
OBJETIVOS
• Conhecer alguns dos algoritmos para processamento de consultas;
• Aprender a otimizar uma consulta;
• Conhecer um plano de execução de consultas.
96 • capítulo 5
5.1 Algoritmos para processamento de consultas
“Uma consulta expressa em uma linguagem de consulta de alto nível, tal como
SQL, deve primeiro passar por uma análise léxica, uma análise sintática e ser va-
lidada”. “ELMASRI, R.; NAVATHE, S., Sistemas de Banco de Dados – pag. 354”.
A análise léxica identifica as palavras-chave da linguagem SQL, enquanto
que a análise sintática identifica a sintaxe de escrita da consulta. A consulta
também deve ser validada verificando-se se seus atributos fazem parte do ban-
co de dados a ser consultado. Somente então, uma representação interna da
consulta é criada, geralmente representada em forma de uma arvore de consul-
ta ou representada na forma de um grafo de consulta.
Após a tradução dessa consulta em uma estrutura que faz sentido para o
SGBD uma estratégia de execução é criada. Em geral, uma consulta pode pos-
suir várias estratégias de execuções diferentes, e o processo de escolha de uma
estratégia adequada para o processamento de uma consulta é chamado de oti-
mização de consulta (o termo “otimização” não é a melhor forma de expres-
sar esse processo. Pois nem sempre o plano de execução escolhido é o melhor.
Encontrar a otimização “perfeita” para um plano de execução pode consumir
recurso e tempo escassos já que uma estratégia razoavelmente eficiente pode
garantir o mesmo resultado com diferenças ínfimas de performance).
A figura 5.1 mostra diferentes passos do processamento de uma consulta
de alto nível. Primeiro, pelo módulo de Tradução é criado uma representação
interna da consulta em uma linguagem que o SGBD irá executar. O módulo oti-
mizador tem a função de produzir um plano de execução, e o gerador de código
gera o código que executa aquele plano. O processador em tempo de execução
do banco de dados tem a função de executar o código da consulta, quer seja no
modo interpretado, quer seja no modo compilado, a fim de obter o resultado
da consulta. Se resultar em um erro em tempo de execução, uma mensagem de
erro é gerada pelo processador em tempo de execução do banco de dados.
capítulo 5 • 97
Consulta em linguagem de alto nível
Tradução
Representação interna
Otimização de Consulta
Representação transformada
Definição de Plano de Execução
Plano de Execução
Gerador de Código
Código de execução
Processador Run-time
Resultado da Consulta
2. Busca binária:
Usa busca binária, que é mais eficiente que a busca linear para encontrar os
valores das condições de busca;
98 • capítulo 5
3. Utilização de um índice primário:
Utiliza o índice primário para recuperar a informação caso o item procu-
rado está no campo de chave única. Observe que essa condição recupera um
único registro;
capítulo 5 • 99
8. Seleção conjuntiva utilizando um índice composto:
Se for possível usar um índice composto criado com a combinação dos atri-
butos envolvidos de cada lado do operador AND pode-se usar esse índice para
recuperar a consulta diretamente;
Sempre que uma cláusula ORDER BY for adicionada a uma operação SELECT,
o resultado recuperado da consulta deve ser ordenado. A ordenação também é
um componente chave nos algoritmos usados no JOIN e em outras operações,
tais como UNION e INTERSECTION.
Um dos algoritmos empregados na ordenação a ser usado quando ORDER
BY for especificado é chamado de Algoritmo para ordenação externa (External
Sorting). Consiste em ordenar pequenas partes também chamadas de runs e
então juntar esses pequenos runs ordenados, criando partes maiores orde-
nadas que por sua vez são fundidas com outras partes também ordenadas,
pelo fato de estar sempre ordenado e juntando pequenas partes esse algorit-
mo recebe o nome de sort-merge (ordena e junta). A figura ao lado descreve
o algoritmo:
100 • capítulo 5
Inicialize:
i = 1;
j = b; {tamanho do arquivo em blocos}
k = nB; {tamanho do buffer em blocos}
m = ( j / k );
{Fase de Ordenação}
While (i <= m) {
- Ler os próximos k blocos do arquivo para o buffer ou se houver menos do que k
blocos restantes, então ler os blocos restantes;
- Ordenar os registros no buffer e gravá-los como um subarquivo temporário;
i = i + 1;
};
While (i <= p) {
n = 1;
q = (j / (k-1));
While (n <= q) {
- Ler os próximos k-1 subarquivos ou os subarquivos restantes (da passa-
gem anterior), um bloco por vez;
- Fundir e gravar como novo subarquivo um bloco por vez;
n = n + 1;
}
j = q;
i = i + 1;
}
capítulo 5 • 101
pidamente. Abaixo temos as quatro técnicas mais comuns para a execução de
junção de dois arquivos:
1. Junção de laços aninhados (nested-loop) (força bruta):
Recupera cada registro na tabela A e verifica se para cada elemento da tabela
B a condição da junção é satisfeita (semelhante a um for dentro de for).
2. Junção de laço único (single-loop):
Se existe um índice para um dos atributos da junção na tabela A, recupera
todos os registros da tabela B, e posteriormente utilize o índice para recuperar
os registros que atendem a junção.
3. Junção sort-merge (ordenação-fusão):
Se as tabelas A e B estão fisicamente ordenados, pode-se correr os registros
simultaneamente e recuperar os dados que atendem a junção. Se não estiverem
ordenados, eles podem ser através de uma ordenação externa.
4. Junção hash (hash-join):
Os registros de A e B são separados em arquivos menores utilizando a mes-
ma junção hash (fase de particionamento). Na segunda fase (fase de investiga-
ção) casa-se os registros correspondentes.
102 • capítulo 5
Uma consulta inicialmente é traduzida para a álgebra relacional, geralmen-
te representada em uma estrutura de dados de árvore de consultas ou de um
grafo de consulta. Após essa representação o analisador sintático otimiza essa
consulta de acordo com regras de heurística.
Uma das principais regras heurísticas é aplicar as operações SELECT e
PROJECT antes de aplicar o JOIN. As operações de SELECT e PROJECT redu-
zem o tamanho de um arquivo, ao passo que o JOIN ao agregar novos dados e
aumentam o tamanho desse arquivo.
As regras de heurísticas devem ser aplicadas nos seguintes passos:
1. Executar operações de SELEÇÃO e PROJEÇÃO primeiramente;
2. A JUNÇÃO só deve ser realizada depois da SELEÇÃO e PROJEÇÃO;
3. Somente os atributos solicitados para o resultado da consulta e os
que realmente são necessários em consultas subsequentes é que devem
ser projetados;
4. Evitar geração de múltiplas tabelas intermediárias;
5. Pesquisar as subexpressões comuns e processá-las somente uma vez.
capítulo 5 • 103
O custo da execução de uma consulta inclui os seguintes componentes:
1. Custo de acesso ao armazenamento secundário:
Esse é o custo de todo processo envolvido no acesso e armazenamento em
memória secundária, geralmente o disco do computador. O processo de leitura
e escrita em disco vai depender dos tipos de estruturas de acesso do arquivo gra-
vado em disco. Se existirem índices e estruturas de busca eficientes, bem como
o quão fragmentado estão os arquivos no disco, esse custo pode ser reduzido.
2. Custo de armazenamento:
Esse é o custo de armazenamento de quaisquer arquivos temporários que
sejam gerados durante a execução das consultas envolvidas no processo.
3. Custo de computação:
Esse é o custo envolvido nos cálculos das operações necessárias durante a
execução da consulta. Tais operações incluem a busca e ordenação das consul-
tas, junções entre tabelas e resultados de funções envolvidas na consulta.
4. Custo do uso de memória:
Esse é o custo referente à quantidade de memória usada durante a execução
da consulta.
5. Custo de comunicação:
Esse é o custo do transporte dos dados resultantes da consulta da origem
para o destino. Para um sistema local, é o custo de leitura em disco e disponi-
bilização da informação na memória ou dispositivo de saída do sistema. Mas
pode ser o custo de disponibilização da informação resultante de uma consul-
ta para um usuário final distante quilômetros da origem. Em bancos de dados
distribuídos, nos quais muitos sites estão envolvidos, o custo de comunicação
também deve ser minimizado. É difícil incluir todos esses componentes de cus-
to em uma função de custo (ponderada) por causa da dificuldade em atribuir
pesos adequados aos componentes do custo. Essa é a razão pela qual algumas
funções de custo consideram apenas o acesso ao disco.
104 • capítulo 5
Considere a seguinte consulta e seu plano de execução:
select (select ContactName from Customers where Customers.CustomerID
= Orders.CustomerID) ContactName,
orders.OrderDate,
Orders.OrderID,
[Order Details].Quantity,
ProductName
from Orders, [Order Details],
Products
where [Order Details].OrderID = Orders.OrderID
and Products.ProductID = [Order Details].ProductID
• 105
capítulo 5
Figura 5.3 – Consuta sem subselect. Fonte: Elaborada pelo autor.
106 • capítulo 5
analisar se o desempenho muda com ou sem o índice. Caso a comparação não
seja conclusiva ou a experiência não se mostre satisfatória, opte pela remoção
do índice.
Tente descobrir o equilíbrio na criação dos índices. Lembre-se que as con-
sultas (SELECTs) são afetadas pelos índices de maneira positiva, pois a infor-
mação indexada faz a busca ser mais rápida. Mas as operações de manipula-
ção de dados (DML) são afetadas negativamente, pois os índices precisam ser
reconstruídos sempre que uma informação é inserida (INSERT) ou removida
(DELETE) de nossa base de dados. Então, se o sistema executar muitas opera-
ções DML, procure não aumentar o número de índices criados.
Para ajudar na escolha da criação de um índice é útil conhecer dois concei-
tos: Seletividade e Densidade. Um índice razoavelmente Seletivo e com baixa
Densidade de maneira geral, é a meta a ser perseguida.
• Seletividade:
Um índice é dito seletivo quando ele ajuda a filtrar poucas linhas de um
grande número de linhas disponíveis. O índice criado pela escolha de uma
chave primária única é dito bastante seletivo, pois em uma busca pela chave,
podemos garantir que apenas um registro será retornado, portanto um índice
seletivo é bem-vindo no sistema.
• Densidade:
Um índice possui densidade elevada quando ajuda a retornar um grande
conjunto de resultados em potencial. E densidade baixa quando retornar pou-
cas linhas. Um índice criado a partir de uma chave primária terá densidade bai-
xa, já que retorna apenas uma linha. Mas observe que para tabelas com pou-
cas informações essa densidade pode aumentar já que sua medida é relativa a
quantidade de informação existente. Portanto em uma tabela com vários regis-
tros onde se consegue criar um índice com densidade baixa esse índice pode
vir a ser útil.
capítulo 5 • 107
ATIVIDADES
01. Diga os principais pontos que você utilizaria para melhorar as consultas abaixo?
a) SELECT * FROM PESSOAS where CPF IS NOT NULL ORDER BY NOME
b) SELECT * FROM PESSOAS where CPF = ‘665.854.455-70’
03. Sobre a sentença: “Clusters são grupos de tabelas que ficam fisicamente armazenadas
juntas porque elas compartilham colunas comuns que são frequentemente utilizadas em con-
junto. Isso melhora o tempo de acesso a disco”. Podemos considerar essa sentença correta?
05. Qual o significado do termo otimização heurística? Discuta as principais heurísticas que
são aplicadas durante a otimização de consultas.
REFERÊNCIAS BIBLIOGRÁFICAS
[1] TENEMBAUM, Aaron - Estruturas de Dados Usando C - Ed. Person Makron Books – 2004.
[2] ELMASRI, R.; NAVATHE, S., Sistemas de Banco de Dados. Pearson Education do Brasil, 4ª.Ed
2005.
[3] PINHEIRO, Álvaro Farias, Fundamentos de Engenharia de Software: Introdução a Banco de
dados, Volume II, 5ª Ed 2015.
[4] MICROSOFT TECHNET, Ajuste do desempenho de consulta. Disponível em: https://technet.
microsoft.com/en-us/library/ms172984(v=sql.110).aspx . Acessado em: 24/04/2016.
GABARITO
Capítulo 1
01. Chave primária, chave estrangeira são conceitos importantes na modelagem de dados,
pois implementam restrições que garantirá ao futuro banco de dados a integridade dos dados.
108 • capítulo 5
• Chave primária:
Atributo ou combinação de atributos que possuem a propriedade de identificar de forma
única uma linha da tabela.
• Chave estrangeira:
A chave estrangeira ocorre quando um atributo de uma relação for chave primária em
outra relação
02. Poderia ser o campo CPF ou o campo RG, pois ambos garantem um atributo único que
garantem a unicidade do registro.
03. Na terminologia do modelo relacional formal, uma linha é chamada tupla, um cabeçalho
de coluna é conhecido como atributo, e a tabela é chamada relação. O tipo de dado que des-
creve os tipos de valores que podem aparecer em cada coluna é representado pelo domínio
de valores possíveis.
04. Seria necessário descobrir o CPF do Rubens ou inserir um valor único de CPF para ele
se quisermos inseri-lo no banco de dados. Uma boa ideia é também ver se alguns dos CPFs
já existem no banco de dados, para evitar um erro na inserção dos registros.
05. Uma tupla é uma linha de registro. Não faz sentido termos 2 linhas de registros iguais.
Principalmente se existir uma chave primária definida.
Capítulo 2
01. Sim é possível. Isso é conhecido como “auto relação”, Onde a chave primária de uma
tabela é relacionada com uma chave secundária da mesma tabela.
02. SELECT FILHOS.NOME, FILHOS.CPF, PAIS.NOME
FROM PESSOAS FILHOS, PESSOAS PAIS
WHERE PAIS.CPF = FILHOS.CPFPAI
03. SELECT FILHOS.NOME, FILHOS.CPF, PAIS.NOME
FROM PESSOAS FILHOS, PESSOAS PAIS, PESSOAS MAES
WHERE PAIS.CPF = FILHOS.CPFPAI
AND MAES.CPF = FILHOS.CPFMAE
04. SELECT UPPER(SOBRENOME) + ‘, ‘ + UPPER(SUBSTRING(NOME,1,1)) + LO-
WER(SUBSTRING(NOME,2)) AS NOME, REPLACE(REPLACE(CPF,’.’,’’),’-’,’’) AS CPF
FROM PESSOAS
05. INSERT INTO PESSOAS (NOME, SOBRENOME, CPF, CPFPAI, CPFMAE)
VALUES (‘João’,’Silva’,’038.053.186-00’,NULL,NULL)
capítulo 5 • 109
06. A primeira soma como os números representados com os pontos decimais, irá retornar
um decimal (resultado = 10.6666).
O segundo, soma números inteiros e irá retornar um inteiro desprezando a parte decimal.
(resultado = 10)
07. SELECT * FROM Orders,
[Order Details],
Products
where [Order Details].OrderID = Orders.OrderID
and Products.ProductID = [Order Details].ProductID
A resposta de qual é melhor é bastante subjetiva, mas o join feito com where e AND
parece ser mais fácil de entender e contruir.
08. SELECT sum(quantity), ProductName FROM [Order Details], Products where
[Order Details].ProductID = Products.ProductID group by ProductName
having( sum(quantity) > 10)
Não podemos usar funções de agregação junto com colunas sem ser especificada a
cláusula GROUP BY. Quando colocamos a coluna ProductName junto a uma função SUM o
SQL não vai conseguir somar e mostrar os diversos nomes de produtos sem que na pesquisa
seja especificado a cláusula GROUP BY. Isso quer dizer, que para qualquer coluna desejada
no SELECT (desde que não seja uma função) ela deve aparecer também na cláusula GROUP
BY. Além disso, se a intenção é mostrar somente os produtos cujas quantidades são maiores
do que 10 por pedido, na consulta deve estar especificada a cláusula HAVING.
09. Essa é uma resposta subjetiva. Mas na opinião do Autor, a maior vantagem de se usar
uma view é poder “esconder” dos usuários valores de colunas que contém informações vitais
para uma empresa. Por exemplo, se existir uma tabela de funcionários e nela conter as infor-
mações de salário, o administrador de banco pode criar uma view com apenas informações
básicas de funcionários e restringir o direito de leitura completa para a tabela funcionário
apenas para alguns usuários da empresa.
10. As consultas em si não contêm nenhum erro. Trata-se de uma consulta usando uma sub-
consultas. Para cada linha de pedido ela traz o nome e o ID do cliente em questão. Ela pode
ser facilmente reescrita fazendo-se o relacionamento entre as tabelas de pedidos (orders) e
clientes (customers) da seguinte forma:
select OrderID, Customers.CustomerID, [CompanyName] from orders, Customers where
Customers.CustomerID = orders.CustomerID.
110 • capítulo 5
Capítulo 3
01. No contexto de banco de dados, um índice é uma estrutura (ou arquivo) auxiliar associa-
do a uma tabela (ou coleção de dados). Sua função é acelerar o tempo de acesso às linhas
de uma tabela, criando ponteiros para os dados armazenados em colunas específicas. O ban-
co de dados usa o índice de maneira semelhante ao índice remissivo de um livro, verifica um
determinado assunto no índice e depois localiza a sua posição em uma determinada página.
02. Referem-se aos conjuntos de um ou mais campos, cujos valores, considerando a com-
binação de valores em caso de mais de uma chave primária, nunca se repetem na mesma
tabela e, desta forma, podem ser usadas como um índice de referência para criar relaciona-
mentos com as demais tabelas do banco de dados.
03. Um índice secundário fornece um meio secundário de acesso a um arquivo para o qual
já existe algum acesso primário. O índice secundário pode ser usado sobre um campo que
é uma chave candidata e possui um valor único em cada registro, ou um campo que não é
chave e que possui valores duplicados.
04. Um arquivo pode ter, no máximo, um campo de classificação física, portanto, ele só terá
um índice primário ou um índice de cluster, mas não ambos.
05. Chamamos de índice denso, o índice que possui uma entrada de índice para cada regis-
tro no arquivo de dados. Um índice esparso, no entanto, tem entradas de índice para somente
alguns valores de pesquisa.
Capítulo 4
01. Em um típico sistema de banco de dados, vários usuários estão fazendo acesso ao ban-
co ao mesmo tempo. Vários aplicativos podem estar acessando os mesmos dados a cada
instante. Desse modo, não é incomum que atualizações, inserções e deleções de registros
estejam ocorrendo ao mesmo tempo. Dessa forma, um controle ao acesso aos dados é es-
sencial para manter a integridade dos dados.
02. Não, pois está ocorrendo apenas uma consulta a dados sem alteração de conteúdo.
03. Sim, já que está ocorrendo uma alteração de dados, outros usuários podem estar aces-
sando o registro. Então, para garantir a operação de update, faz-se necessário o controle
da transação.
04. D.
05. Sim, em alguns sistemas de banco de dados (Oracle por exemplo) é possível criar pon-
tos de controle usando o comando SAVEPOINT.
capítulo 5 • 111
Capítulo 5
01.
a) Se ordenações pelo campo NOME forem constantes seria interessante criar um índice
para essa tabela a partir desse campo. Isso agilizaria a consulta, pois com um índice
ordenado a ordenação do resultado seria mais rápido.
b) Se o campo CPF for uma chave primária, nada precisaria ser feito, já que as chaves
primárias geram índices ideais para serem usados em pesquisas WHERE.
02. Podemos usar o plano de execução para “ver” como uma consulta é organizada. Testan-
do várias consultas e analisando os planos de execução poderemos optar pela consulta com
o melhor plano de execução.
03. Sim. Essa é a típica criação de um índice clustering para uma coluna bastante acessada
em pesquisas que otimizará a performance das pesquisas quando fizer referência a esse
conjunto de dados.
04.
a) Custo de acesso ao armazenamento secundário;
b) Custo de armazenamento;
c) Custo de computação;
d) Custo do uso de memória;
e) Custo de comunicação
05. Na otimização heurística, algumas regras são aplicadas para melhorar o desempenho
da execução e da transformação das consultas em diversas expressões equivalentes. As
regras são:
Executar operações de SELEÇÃO e PROJEÇÃO primeiramente;
A JUNÇÃO só deve ser realizada depois da SELEÇÃO e PROJEÇÃO;
Somente os atributos solicitados para o resultado da consulta e os que realmente são
necessários em consultas subsequentes é que devem ser projetados;
Evitar geração de múltiplas tabelas intermediárias;
Pesquisar as subexpressões comuns e processá-las somente uma vez;
A utilização dessas regras heurísticas influencia no plano de execução da consulta, pois
uma ordem de execução das operações é determinada e também quais os recursos serão
utilizados no plano, por exemplo, os índices.
112 • capítulo 5