Artigo sobre banco de dados

Propaganda
Seminário S2i:
Banco de Dados - MySQL e PostgreSQL
Marcelo Moraes Minasi 0013021-4
Florianópolis, 26 de abril de 2004.
Lista de Tabelas
1
2
3
4
5
6
7
Tabela do fornecedor. . . . . . . . . . . . . . . . . .
Tabela das peças. . . . . . . . . . . . . . . . . . . . .
Tabela do relacionamento entre fornecedores e peças.
Dependências: um caso errado e outro correto. . . .
Tabela do fornecedor. . . . . . . . . . . . . . . . . .
Tabela da variável SEGUNDA e FP. . . . . . . . . .
Tabela da variável FC e CS. . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4
4
5
8
9
10
11
Componentes de um sistema de banco de dados. . . . . . . . . . . . . .
Relacionamento como entidade. . . . . . . . . . . . . . . . . . . . . . . .
Primeira ilustração da arquitetura de três nı́veis. . . . . . . . . . . . . .
Segunda ilustração da arquitetura de três nı́veis. . . . . . . . . . . . . .
Tela após a simples execução de um cliente SQL e seu status. . . . . . .
Benchmark de banco de dados: páginas da web retornadas por segundo.
Benchmark de banco de dados: as respostas mais rápidas. . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
4
7
7
16
19
20
O banco de dados de fornecedores e peças (definição dos dados). . . . . . . . .
Exemplo de domı́nios usando DOMAIN. . . . . . . . . . . . . . . . . . . . . . .
Exemplo de falha de verificação de tipo em domı́nios. . . . . . . . . . . . . . . .
Exemplo de restrição usando SELECT. . . . . . . . . . . . . . . . . . . . . . .
Exemplo de projeção usando SELECT. . . . . . . . . . . . . . . . . . . . . . . .
Exemplo de projeção simplificada usando SELECT. . . . . . . . . . . . . . . .
Exemplo de junção usando SELECT. . . . . . . . . . . . . . . . . . . . . . . . .
Exemplo de INSERT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exemplo de UPDATE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exemplo de DELETE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exemplo de CREATE VIEW. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Exemplo de uma consulta sobre uma VIEW. . . . . . . . . . . . . . . . . . . .
Exemplo de eliminação de registro na VIEW e suas implicações na tabela real.
Exemplo de SQL Embutida com API para Java. . . . . . . . . . . . . . . . . .
Exemplo de SQL Embutida com API para C++. . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6
12
13
13
13
14
14
15
15
16
16
17
17
21
23
Lista de Figuras
1
2
3
4
5
6
7
Códigos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Sumário
1 Introdução
1.1 Instalação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
3
2 Conceituação básica
3
3 Projeto
3.1 Arquitetura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Formas normais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
5
5
4 SQL
4.1 Operações de definição . . . . . . . .
4.2 Operações de manipulação de dados
4.3 Operações de Atualização . . . . . .
4.4 Sumário das instruções SQL . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
12
13
13
14
5 Exemplo
15
6 APIs - Application Program Interfaces
6.1 Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2 C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
18
18
7 Estudo comparativo entre MySQL e PostgreSQL
18
1
Introdução
Esse documento foi fortemente baseado na referência [C. 00]. Tenta-se dar uma boa base
dos conceitos iniciais envolvendo bando de dados e do padrão SQL, mostrando-se, no final,
um exemplo, uma simples comparação (benchmark ) envolvendo alguns sistemas de bancos de
dados e algumas APIs - application program interface. Um interessante trabalho posterior seria
algumas ferramentas gráficas para construção de um banco de dados e uma melhor comparação
de alguns sistemas de bancos de dados, como MySQL, PostreSQL, etc.
1.1
Instalação
Assume-se aqui que o leitor conseguiu instalar perfeitamente um servidor de banco de dados
onde possa criar bancos e modificá-los, como também executar buscas exemplificadas nesse
documento através de query da SQL.
Como a instalação varia conforme o sistema operacional, indica-se aqui apenas alguns ponteiros para páginas de instalação de dois dos mais usados programas para sistemas de gerenciamento
de banco de dados: MySQL [MySb] na referência [MySa] e PostgreSQL em [Pos].
Outra referência interessante para instalação do MySQL [MySb] é: http://www.devshed.com
/c/a/MySQL/MySQL-Installation-and-Configuration/.
Após a instalação, algumas rotinas ainda precisam ser executadas, para maiores detalhes,
veja o ponteiro: http://dev.mysql.com/doc/mysql/en/Unix post-installation.html.
2
Conceituação básica
Sistema de Banco de Dados é simplesmente um sistema computadorizado de armazenamento
de registros, composto basicamente por quatro partes: dados (banco de dados), software (sistema
de gerenciamento do banco de dados), hardware (armazenamento fı́sico) e usuários (programadores de aplicação, usuários finais e DBA - Administrador). Tais registros são as linhas de uma
tabela, cujas colunas são os dados. Essa tabela é um arquivo computadorizado.
Figura 1: Componentes de um sistema de banco de dados.
Um banco de dados é uma coleção de dados persistentes (não que eles durem para sempre,
mas diferem de entradas, saı́das, etc.) utilizada pelos sistemas de aplicação.
2
CONCEITUAÇÃO BÁSICA
4
Sua utilização possui as seguintes vantagens: compartilhamento de dados, redundância controlada (reduzida), inconsistência controlada, suporte a transações (operações atômicas: tudo ou
nada, ou atualiza todas as tabelas necessárias, ou nenhuma; que em conjunto com o log implica
consistência), integridade (restrições de integridade, por exemplo, idade ≤ 0), maior segurança
(senhas), aplicações independente de dados, etc.
Uma tabela (variável de relação) contém os dados relativos a um conjunto de entidades
idênticas (livro, tema, leitor e requisição). Cada linha (tuplo) caracteriza uma entidade desse
conjunto. Cada coluna (atributo) representa uma caracterı́stica dessa entidade.
Cada tabela apresenta um identificador único, chamado de chave primária. Nem sempre
é vantagem acrescentar mais um campo designado a ser essa chave (como uma numeração
seqüencial e cı́clica), pois essa pode ser limitada pelo tamanho do tipo de dado desse campo.
Assim, ela pode ser constituı́da de vários dados agrupados da tabela. Por exemplo, o BD da
Eletrosul apresenta 3.000.000.000 de registros mensais!
As entidades são composta por registros, que são instâncias daquele tipo, por exemplo: a
entidade carro pode possuir os registros carroA, carroB, Monza etc. Além de entidades, normalmente num banco de dados, haverá relacionamentos entre entidades, que segundo o paradigma
relacional, também são representadas em tabelas. Observe a figura [2]. Isso será melhor explicado mais abaixo.
A seguir, apresenta-se alguns conceitos básicos no contexto de banco de dados:
Chave primária é um identificador único para cada tuplo de uma tabela. Cada tabela deve ter
uma chave primária. Uma chave primária pode ser constituı́da por um ou mais atributos.
Chave estrangeira é a utilização da chave primária numa outra tabela para se poder criar um
relacionamento.
Transação é uma unidade lógica de trabalho (atômicas).
Figura 2: Relacionamento como entidade.
#Fornecedor
1
2
NomeF
A
B
Tabela 1: Tabela do fornecedor.
#Peça
1
2
NomeP
Parafuso
Prego
Tabela 2: Tabela das peças.
Bancos de dados relacionais são sistemas de banco de dados baseados em uma fundamentação
normal (teórica) chamada de modelo relacional de dados, que apresenta três aspectos:
• Aspecto estrutural: os dados são representados por tabelas, e só tabelas - propriedade de
fechamento: a saı́da de uma operação é também uma tabela, o que garante que a saı́da de
uma operação pode ser a entrada de outra.
#Peça
1
2
#Fornecedor
1
2
Qtdade
2000
3000
Tabela 3: Tabela do relacionamento entre fornecedores e peças.
• Aspecto de integridade: essas tabelas satisfazem a certas condições de integridade;
• Aspecto manipulativo: os operadores disponı́vies para manipular tabelas derivam umas de
outras - os três mais importantes são:
Restrição (DEPTOs nos quais ORÇAMENTO > R$8 milhões),
Projeção (DEPTOs sobre #DEPTO, ORÇAMENTO) e
Junção (DEPTOs e EMPREGADOs sobre #DEPTO).
Aqueles registros devem sofrer algum tipo de operação em algum momento, como:
• Acrescentar novos arquivos (CREATE TABLE);
• Inserir novos dados em arquivos (INSERT);
• Buscar (SELECT), alterar (UPDATE) e eliminar dados em arquivos existentes (DELETE).
Esses exemplos são todos expressos em uma “linguagem” chamada SQL. Ela será melhor
explicada mais abaixo [4].
3
Projeto
3.1
Arquitetura
Geralmente, o projeto de um BD se dá em três nı́veis, como observado nas figuras [3] e [4]:
1. Interno (fı́sico): como os dados são fisicamente armazenados (número de bytes de cada
campo, etc.);
2. Externo (lógico do usuário): como os dados são vistos por cada usuário individualmente.
CREATE VIEW teste AS (EMP WHERE SALÁRIO > 3K) { #EMP, NOMEEMP,
SALÁRIO } ;
3. Conceitual (lógico comunitário): intermediário entre os dois.
Na concepção de um BD, tanto a Linguagem de definição de dados (DDL), como ilustrado no
código [1], como a linguagem de manipulação de dados (DML) são transparentes para o usuário.
De um ponto de vista de mais alto nı́vel, pode ser considerado como uma arquitetura cliente/servidor.
3.2
Formas normais
O assunto de normalização é apenas uma formalização de uma idéia simples e muito usada
na prática. Idéia que consiste em fazer um projeto de banco de dados seguindo o paradigma
“um fato em um lugar”, isto é, evitar redundância. Além disso, a normalização nos ajuda a
estruturar o banco de dados de forma a tornar mais fácil as atualizações de uma única tupla do
que seria caso esse banco não estivesse normalizado.
3
PROJETO
6
1
2
3
4
TYPE #F . . . ;
TYPE NOME . . . ;
TYPE #P . . . ;
TYPE QTD . . . ;
6 VAR F BASE RELATION
7
{ #F
#F o r n e c e d o r ,
8
NOME NomeF }
9
PRIMARY KEY { # F o r n e c e d o r e s } ;
11 VAR P BASE RELATION
12
{ #P
#Peca ,
13
NOME NomeP }
14
PRIMARY KEY { # Peca } ;
16 VAR FP BASE RELATION
17
{ #F
#F o r n e c e d o r ,
18
#P
#Peca ,
19
QTD
Qtdade }
20
PRIMARY KEY {# F o r n e c e d o r , # Peca }
21
FOREIGN KEY { # F o r n e c e d o r } REFERENCES F
22
FOREIGN KEY { # Peca }
REFERENCES P ;
Código 1: O banco de dados de fornecedores e peças (definição dos dados).
Algumas variáveis poderiam, mesmo estando normalizadas - no sentido do parágrafo anterior
- possuı́rem propriedades indesejáveis. É justamente nesse sentido que vêm os princı́pios de
normalização avançada, ou formas normais. Esses princı́pios nos permitem reconhecer esses
casos e substituir essas variáveis por outras mais desejáveis de algum modo.
Dizemos que uma variável está em uma forma normal se ela satisfaz a um certo conjunto
prescrito de condições. Por exemplo, dizemos que uma variável de relação - que modela um
relacionamento - está na segunda forma normal (2FN) se, e somente se, ela está em 1FN e
também satisfaz uma outra determinada condição, descrita mais abaixo em 3.2.
Numerosas formas normais foram definidas por volta de 1972. As três primeiras por Codd em
[E. 72]. Mais tarde, Boyce e Codd definiram também uma “outra terceira” forma normal, mais
abrangente, conhecida como forma normal de Boyce/Codd (FNBC). Subsequentemente,
Fagin definiu ainda a quarta e a quinta formas normais. A referência [E. 72] definiu também
um procedimento de normalização, através do qual uma variável de relação que está em
alguma forma normal especı́fica pode ser substituı́da por um conjunto de variáveis de relação
em alguma forma mais desejada. Esse procedimento é reversı́vel, o que significa que o processo
de normalização preserva informações.
Embora existam outras formas normais além dessas seis, esse documento abrangerá apenas
as três primeiras, visto que a implementação de um banco de dados projetado de forma que
suas variáveis estejam na 3FN é uma boa solução de compromisso entre a complexidade dos
procedimentos de normalização subsequentes e o nı́vel de caracterı́sticas desejadas obtidas (baixa
redundância, integridade, etc.).
O processo de normalização consiste em decompor uma variável de relação em outras
variáveis mais desejadas. Esse processo deve ser necessariamente ser perdas, i. e. reversı́vel.
3
PROJETO
7
Figura 3: Primeira ilustração da arquitetura de três nı́veis.
Figura 4: Segunda ilustração da arquitetura de três nı́veis.
Para que uma decomposição1 sem perdas seja realizada, e assim seja possı́vel recompor2 o
conjunto de informações, precisa-se respeitar o conceito de dependência funcional descrito a
seguir.
Para entender melhor a importância do conceito de dependência funcional, imagine o
seguinte problema: se R1 e R2 são projeções de alguma variável de relação R, e se R1 e R2 em
conjunto incluem todos os atributos de R, que condições devem ser satisfeitas para garantir que
a junção de R1 e R2 nos dará de volta a variável de relação original R? Ver exemplo na tabela
[4] abaixo. É aqui que entram as dependências funcionais.
Seja R uma variável de relação, e sejam X e Y subconjuntos arbitrários do conjunto de
atributos de R. Então, dizemos que Y é funcionalmente dependente de X – em sı́mbolos, X →
Y, (”X seta Y”), se e somente se em todo valor válido de R, cada valor X tem associado a ele
exatamente um valor Y. Em outras palavras, em todo valor possı́vel válido de R, sempre que
1
2
O operador da decomposição na álgebra relacional é, na verdade, o de projeção.
O operador da recomposição na álgebra relacional é, na verdade, o de junção.
3
PROJETO
8
#Fornecedor
F3
F5
#Fornecedor
Caso correto
F3
F5
Caso errado
#Fornecedor
F3
F5
STATUS
30
30
STATUS
30
30
STATUS
30
30
CIDADE
Paris
Atenas
#Fornecedor
F3
F5
STATUS
30
30
CIDADE
Paris
Atenas
CIDADE
Paris
Atenas
Tabela 4: Dependências: um caso errado e outro correto.
duas tuplas concordam sobre seu valor X, elas concordam também sobre seu valor Y.
Todo conjunto de DFs – dependências funcionais – é equivalente a pelo menos um conjunto
irredutı́vel. Se I é um conjunto irredutı́vel equivalente a S, a imposição das DFs em I imporá
automaticamente as DFs em S. Defini-se um conjunto S de DFs como irredutı́vel se e somente
se:
1. O lado direito (o dependente) de cada DF em S contém apenas um atributo;
2. O lado esquerdo (o determinante) de cada DF em S é por sua vez irredutı́vel - significando
que nenhum atributo pode ser descartado do determinante sem converter S em algum
conjunto não equivalente a S;
3. Nenhuma DF em S pode ser descartada de S sem converter S em em algum conjunto não
equivalente a S.
Existem Diagramas DF que representam convenientemente essas dependências. Isso é interessante porque as DFs possuem uma noção semântica, cuja interpretação só depende do
projetista. Por exemplo, #F → CIDADE significa que cada fornecedor está localizado em exatamente uma cidade.
Apenas para se ter uma noção do ponto que se deseja atingir, descreve-se informalmente o
que seria a terceira forma normal (3FN).
Terceira forma normal: uma variável está na 3FN se e somente se os atributos não-chaves
(qualquer atributo que não participa da chave-primária da variável de relação) são:
• Mutuamente independentes, i. e., se nenhum deles é funcionalmente dependentes de qualquer combinação dos outros;
• Irredutivelmente dependentes da chave primária.
O fato de dois ou mais atributos serem mutuamente independentes quer dizer que cada um
deles pode ser atualizado independentemente dos demais.
Descreve-se a seguir o processo de normalização. Antes, a definição da primeira forma
normal:
Primeira forma normal: uma variável de relação está em 1FN se, e somente se, em todo
valor válido dessa variável de relação, cada tupla contém exatamente um valor para cada
atributo.
3
PROJETO
9
Por exemplo:
PRIMEIRA { #F, STATUS, #P, QDE, CIDADE }
PRIMARY KEY { #F, #P } ;
#F
F1
F1
F1
F1
F1
F1
F2
F2
F3
F4
F4
F4
STATUS
20
20
20
20
20
20
10
10
10
20
20
20
CIDADE
Londres
Londres
Londres
Londres
Londres
Londres
Paris
Paris
Paris
Londres
Londres
Londres
#P
P1
P2
P3
P4
P5
P6
P1
P2
P2
P2
P4
P5
QDE
300
200
400
200
100
100
300
400
200
200
300
400
Tabela 5: Tabela do fornecedor.
A principal desvantagem é a quantidade excessiva de redundâncias, que são também chamadas de anomalias de atualização. No exemplo acima, não dá para inserir a informação de que
um determinado fornecedor está numa cidade especı́fica até que ele efetivamente forneça pelo
menos uma peça. E se eliminarmos uma tupla da tabela acima, eliminaremos talvez muito mais
informações que gostarı́amos.
Para solucionar, utiliza-se o processo de normalização, que informalmente pode ser entendido
agora como uma processo de desempacotamento: inserir informações logicamente isoladas em
variáveis de relações separadas.
Assim, a solução para esses problemas seria:
SEGUNDA { #F, STATUS, CIDADE }
PRIMARY KEY { #F } ;
e
FP{ #F, #P, QDE }
PRIMARY KEY { #F, #P }
FOREIGN KEY { #F } REFERENCES SEGUNDA;
Assim, deve ficar claro que essa estrutura resolve todos os problemas com operações de
atualização descritos anteriormente.
Segunda forma normal: uma variável está na 2FN se e somente se ela está na 1FN e todo
atributo não-chave é irredutivelmente dependente da chave primária.
Mas a estrutura SEGUNDA ainda sofre pela falta de independência mútua entre seus atributos não-chaves. Mais detalhadamente, a dependência de STATUS sobre #F, embora seja
funcional e, de fato, irredutı́vel, é transitiva (através de CIDADE): cada valor de #F determina uma CIDADE e esta, por sua vez, determina o valor de STATUS. Dependências transitivas
levam também a anomalias de atualização. Mais uma vez a solução é desempacotar, transformar
a variável SEGUNDA em:
3
PROJETO
10
#F
F1
F2
SEGUNDA
F3
F4
F5
#F
F1
F1
F1
F1
F1
F1
FP
F2
F2
F2
F3
F4
F4
F4
STATUS
20
10
10
20
30
#P
P1
P2
P3
P4
P5
P6
P1
P2
P3
P2
P2
P4
P5
CIDADE
Londres
Paris
Paris
Londres
Atenas
QDE
Tabela 6: Tabela da variável SEGUNDA e FP.
FC { #F, CIDADE }
PRIMARY KEY { #F }
FOREIGN KEY { CIDADE } REFERENCES CS ;
e
CS{ CIDADE, STATUS }
PRIMARY KEY { CIDADE } ;
Terceira forma normal: uma variável está na 3FN se e somente se ela está em 2FN e todo
atributo não-chave é dependente de forma não transitiva da chave primária.
Uma observação importante a ser feita é que o nı́vel de normalização de uma variável de
uma relação dada é uma questão de semântica, não apenas uma questão de valores de dados
que essa variável de relação possa conter em algum momento particular. Para resumir, pode-se
dizer que para se chegar ao nı́vel da 3FN, deve-se realizar duas operações:
1. Dada a variável de relação R como esta: (Para reduzir dependências, redundâncias triviais)
R { A, B, C, D } PRIMARY KEY { A, B } ;
Deve-se substituir R por suas duas projeções R1 e R2:
#F
F1
F2
FC
F3
F4
F5
CIDADE
Londres
Paris
Paris
Londres
Atenas
CIDADE
Atenas
CS
Londres
Paris
STATUS
30
20
10
Tabela 7: Tabela da variável FC e CS.
R1 { A, D } PRIMARY KEY{ A, D } ;
R2 { A, B, C } PRIMARY KEY { A, B } FOREIGN KEY { A } REFERENCES R1 ;
2. Dada a variável de relação R como esta: (Para reduzir dependências transitivas, e.g. A →
B e B → C)
R { A, B, C } PRIMARY KEY { A } ;
Deve-se substituir R por suas duas projeções R1 e R2:
R1 { B, C } PRIMARY KEY{ B } ;
R2 { A, B } PRIMARY KEY { A } FOREIGN KEY { B } REFERENCES R1 ;
4
SQL
A SQL é uma linguagem padrão para interação com banco de dados relacionais. Originalmente, o nome ”SQL”significava Structured Query Language (Linguagem de Consulta Estruturada) e se pronunciava ”sequel”. Porém, agora a linguagem se transformou num padrão, e o seu
nome agora é apenas um nome - não é oficialmente uma abreviatura para alguma coisa - e a
pronúncia pendeu para ”esse-quê-éle”. Seu nome oficial é International Standard Database
Language SQL (1992), largamente referenciada na literatura por SQL/92 ou SQL2, que foi
a grande revisão do padrão proposto segundo o padrão SQL.
Posteriormente, teve-se um desenvolvimento da SQL2 para a SQL3, no que concerne ao
suporte a objetos. Mais informações a respeito do suporte a objetos podem ser obtidas no
seguinte ponteiro: http://www.objs.com/x3h7/sql3.htm.
Conceitualmente, SQL é um padrão relacional, i.e., não-procedural (nı́vel de abstração maior
que C++, por exemplo): não se indica como mas o quê se quer. A tarefa de ”como” executar é
definida pelo otimizador do SGBD.
Um tutorial de SQL pode ser obtido em: http://www.devshed.com/c/a/MySQL/A-TechnicalTour-of-MySQL/. Uma simples referência de quais diretivas são padronizadas e suas sintaxes
pode ser obtidas facilmente em http://www.1keydata.com/sql/sql.html.
4
SQL
12
Uma referência excelente para que deseja saber mais sobre SQL é o ponteiro http://sqlzoo.net/.
Ele possui uma ferramenta interativa para se contruir declarações SQL e testá-las sobre diferentes
bancos de dados.
4.1
Operações de definição
Na SQL3 é possı́vel definir-se domı́nios próprios do usuário, na SQL2 não. Aqui, os domı́nios
serão considerados como tipos, mas uma discussão um pouco mais profunda mostra que eles estão
longe de serem a mesma coisa, como mostra o capı́tulo 4 de [C. 00]. Os tipos internos permitidos
pela SQL são:
• CHARACTER [ VARYING ] (n);
• BIT [ VARYING ] (n);
• NUMERIC (p,q);
• DECIMAL (p,q);
• INTEGER;
• SMALLINT;
• FLOAT (p);
• DATE;
• TIME;
• TIMESTAMP;
• INTERVAL.
Como dito anteriormente, os domı́nios em SQL não são tipos verdadeiros. Em SQL, eles
servem apenas para permitir que um tipo embutido, já definido, receba um nome que possa ser
usado como abreviação por várias colunas em diversas definições de tabelas. Um exemplo de
domı́nios podem ser vistos no código [2].
1 CREATE DOMAIN t i p o F # CHAR( 5 ) ;
2 CREATE DOMAIN t i p o P # CHAR( 6 ) ;
4 CREATE TABLE F ( t i p o F # F # , . . . ) ;
5 CREATE TABLE P ( t i p o P # P # , . . . ) ;
6 CREATE TABLE FP ( t i p o F # F#, t i p o P # P # , . . . ) ;
Código 2: Exemplo de domı́nios usando DOMAIN.
Como domı́nio não constitui uma tipagem forte e, portanto, não existe uma verificação de
tipo verdadeira, exige-se muito cuidado ao usá-la. Por exemplo, dadas as definições do código [2],
a operação de SQL descrita no código [3] não falhará em nenhuma verificação de tipo, embora
logicamente devesse falhar.
Pode-se criar uma base de dados no sistema de gerenciamento de banco de dados através da
instrução CREATE DATABASE nome bd . Ela cria uma base da dados vazia. A partir daı́, a
4
SQL
13
1 SELECT ∗
2 FROM FP
3 WHERE F# = P# ;
Código 3: Exemplo de falha de verificação de tipo em domı́nios.
instrução necessária para se criar tabelas, já mostrada acima pela facilidade em seu uso e pelo
seu caráter auto-explicativo, é CREATE TABLE nome (tipoColuna1 nomeColuna1, tipoColuna2
nomeColuna2, ) . Essa instrução pode ser passada com mais parâmetros. Para mais informações,
consulte [MyS04].
Depois de criada uma tabela, pode-se alterá-la através da instrução ALTERTABLE nome
ADD tipoColuna nomeColuna . Ela inclui uma coluna à uma tabela já existente. Para remover
um coluna, basta trocar o ADD por DROP, que será visto mais adiante.
Finalmente, o último dos mais importantes comandos de definição de dados, é o DROP.
Essa instrução permite excluir base de dados DROP DATABASE nome bd ou mesmo tabelas
DROP TABLE nome inteiras. Para a exclusão de simples registros, usa-se DELETE, que será
explicado mais adiante.
4.2
Operações de manipulação de dados
Como dito anteriormente, os três principais aspectos manipulativos de um banco de dados
relacional são: restrição, projeção e junção. Essas três operações podem ser implementadas pela
instrução SELECT. Abaixo tem-se alguns exemplos que comprovam essa idéia.
1 SELECT #F, #P , QDE
2 FROM
FP
3 WHERE QDE < 1 5 0 ;
Código 4: Exemplo de restrição usando SELECT.
1 SELECT F#, NomeF
2 FROM
F ;
Código 5: Exemplo de projeção usando SELECT.
Note que o código [5] acima pode ser simplificado como o código [6] abaixo.
Obs.: Às vezes pode ser necessário o uso de nomes qualificados para tirar a ambiguidade
de referências à colunas, por exemplo: P.P#, FP.P#. Inclusive o ’*’ pode ser qualificado, como
em ’F.*’.
4.3
Operações de Atualização
As principais operações de atualização definidas pela SQL são a inserção (INSERT), atualização (UPDATE) e eliminação (DELETE) de registros. É interessante notar que a eliminação
de tabelas possui uma diretiva especial (DROP) já mencionada anteriormente em 4.1.
O exemplo [8] abaixo pressupões que já exista uma tabela com o nome temp, com duas colunas, P# e PESO. Essa instrução insere nessa tabela números de peças e pesos correspondentes
a todas as peças vermelhas.
1 SELECT ∗
2 FROM
F ;
Código 6: Exemplo de projeção simplificada usando SELECT.
1 SELECT F . F#, P#, NomeF
2 FROM
F , FP
3 WHERE F . F# = FP . F# ;
Código 7: Exemplo de junção usando SELECT.
O próximo exemplo, código [9], atualiza o status de tidis is fornecedores em Paris, duplicandoo.
A instrução DELETE, no exemplo 10, elimina todas as remessas correspondentes à peça P2.
Já foi citado em [3.1] que pode-se criar visões no projeto de um banco de dados. Elas
representam o nı́vel mais externo da arquitetura de um banco. Em SQL pode-se criar visões
a partir da diretiva CREATE VIEW. A partir daı́, essa visão é tratada exatamente como uma
tabela, mas que não está implementada fisicamente. Um exemplo de como criar um visão e
de uma consulta de SQL sobre essa visão pode ser observada abaixo nos códigos [11] e [12]
respectivamente.
É interessante notar que qualquer alteração sobre uma VIEW, afetará diretamente a tabelea
correspondente que está fisicamente implementada. Imagine a seguinte visão criada como mostra
o código [13]. A operação de exclusão executada na linha 6, é o mesmo que executar a operação
da linha 8 sobre a tabela “pai” da visão.
4.4
Sumário das instruções SQL
As instruções mais comuns usadas em SQL e mencionadas anteriormente nesse documento
são: CREATE DOMAIN, CREATE TABLE, CREATE DATABASE, CREATE VIEW, ALTER
DOMAIN, ALTER TABLE, ALTER VIEW, INSERT, UPDATE, DELETE, DROP DOMAIN,
DROP TABLE, DROP VIEW, DROP DATABASE.
Segue abaixo uma relação resumida e simplificada das palavras reservadas definidas pelo
padrão SQL.
Do padrão SQL2 de 1992, dentre outras mais comuns, tem-se: AFTER, ALIAS, ASYNC, BEFORE, BOOLEAN, BREADTH, COMPLETION, CALL, CYCLE, DATA, BETWEEN, BIT,
BIT LENGTH, BOTH, CASCADE, CASCADED, CASE, CAST, CATALOG, CHAR LENGTH,
CHARACTER LENGTH, COALESCE, COLLATE, COLLATION, COLUMN, CONNECT,
CONNECTION, CONSTRAINT, CONSTRAINTS, CONVERT, CORRESPONDING, CROSS,
CURRENT DATE, CURRENT TIME, CURRENT TIMESTAMP, CURRENT USER, DATE,
DAY, DEALLOCATE, DEFERRABLE, DEFERRED, DESCRIBE, DEPTH, DICTIONARY,
EACH, ELSEIF, EQUALS, GENERAL, IF, IGNORE, LEAVE, DESCRIPTOR, DIAGNOSTICS, DISCONNECT, DOMAIN, DROP, ELSE, END-EXEC, EXCEPT, EXCEPTION, EXECUTE, EXTERNAL, EXTRACT, FALSE, FIRST, FULL, GET, GLOBAL, HOUR, IDENTITY, IMMEDIATE, INITIALLY, INNER, INPUT, INSENSITIVE, INTERSECT, INTERVAL, ISOLATION, JOIN, LAST, LEADING, LEFT, LEVEL, LOCAL, LOWER, MATCH,
MINUTE, MONTH, NAMES, NATIONAL, LESS, LIMIT, LOOP, MODIFY, NEW, NONE,
OBJECT, OFF, OID, OLD, NATURAL, NCHAR, NEXT, NO, NULLIF, OCTET LENGTH,
ONLY, OUTER, OUTPUT, OPERATION, OPERATORS, OTHERS, PARAMETERS, PENDANT, PREORDER, PRIVATE, OVERLAPS, PAD, PARTIAL, POSITION, PREPARE, PRE-
1 INSERT
2 INTO temp (
3
SELECT
4
FROM
5
WHERE
P#, PESO )
P#, PESO
P
COR = ’ Vermelha ’ ;
Código 8: Exemplo de INSERT.
1 UPDATE F
2 SET STATUS = STATUS ∗ 2
3
WHERE CIDADE = ’ P a r i s ’ ;
Código 9: Exemplo de UPDATE.
SERVE, PRIOR, READ, PROTECTED, RECURSIVE, REF, REFERENCING, REPLACE,
RESIGNAL, RETURN, RELATIVE, RESTRICT, REVOKE, RIGHT, ROWS, SCROLL, SECOND, SESSION, RETURNS, ROLE, ROUTINE, ROW, SAVEPOINT, SEARCH, SENSITIVE, SEQUENCE, SESSION USER, SIZE, SPACE, SQLSTATE, SUBSTRING, SYSTEM USER,
SIGNAL, SIMILAR, SQLEXCEPTION, SQLWARNING, STRUCTURE, TEST, THERE, TEMPORARY, THEN, TIME, TIMESTAMP, TIMEZONE HOUR, TIMEZONE MINUTE, TRAILING, TRANSACTION, TRANSLATE, TRANSLATION, TRIM, TRUE, UNKNOWN, TRIGGER, TYPE, UNDER, VARIABLE, VIRTUAL, VISIBLE, WAIT, WHILE, UPPER, USAGE,
USING, VALUE, VARCHAR, VARYING, WHEN, WRITE, YEAR, WITHOUT, ABSOLUTE,
ACTION, ADD, ALLOCATE, ALTER, ARE, ASSERTION, AT, ZONE.
Do padrão SQL3 de 1998, dentre outras mais comuns, tem-se: ACTION, ACTOR, AFTER, ALIAS, ASYNC, ATTRIBUTES, BEFORE, BOOLEAN, BREADTH, COMPLETION,
CURRENT PATH, CYCLE, DATA, DEPTH, DESTROY, DICTIONARY, EACH, ELEMENT,
ELSEIF, EQUALS, FACTOR, GENERAL, HOLD, IGNORE, INSTEAD, LESS, LIMIT, LIST,
MODIFY, NEW, NEW TABLE, NO, NONE, OFF, OID, OLD, OLD TABLE, OPERATION,
OPERATOR, OPERATORS, PARAMETERS, PATH, PENDANT, POSTFIX, PREFIX, PREORDER, PRIVATE, PROTECTED, RECURSIVE, REFERENCING, REPLACE, ROLE, ROUTINE, ROW, SAVEPOINT, SEARCH, SENSITIVE, SEQUENCE, SESSION, SIMILAR, SPACE,
SQLEXCEPTION, SQLWARNING, START, STATE, STRUCTURE, SYMBOL, TERM, TEST,
THERE, TRIGGER, TYPE, UNDER, VARIABLE, VIRTUAL, VISIBLE, WAIT, WITHOUT,
CALL, DO, ELSEIF, EXCEPTION, IF, LEAVE, LOOP, OTHERS, RESIGNAL, RETURN,
RETURNS, SIGNAL, TUPLE, WHILE.
5
Exemplo
Apenas algumas definições interessantes:
Nome do servidor:
Nome do cliente:
mysqld ou mysqld.exe;
myslq ou mysql.exe.
Um exemplo de um comando tı́pico para iniciar o cliente é:
c:\mysql\bin\mysql -h nome.do.host -u nomeDoUsuario -p nomeDaBaseDeDados
Onde:
5
EXEMPLO
16
1 DELETE
2 FROM FP
3 WHERE P# = ’ P2 ’ ;
Código 10: Exemplo de DELETE.
1 CRETE VIEW b o m f o r n e c e d o r
2
AS SELECT F#, STATUS , CIDADE
3
FROM F
4
WHERE STATUS > 1 5 ;
Código 11: Exemplo de CREATE VIEW.
nome.do.host é o endereço do computador que está rodando o servidor;
nomeDoUsuario é o nome do usuário;
nomeDaBaseDeDados é o nome da base de dados que será usada;
-p é a opção que exige um prompt para a senha do usuário.
De um modo mais simple ainda, basta o comando: mysql},para que se tenha a seguinte
conexão observada na figura [5]. Note que a conexão se fez, por padrão, com os seguinte atributos:
usuário, minasi - quem executou o programa; host, como nenhum argumento foi passado na
chamada do programa, localhost; dentre outros.
Figura 5: Tela após a simples execução de um cliente SQL e seu status.
A partir do prompt fornecido pelo programa cliente, pode-se fazer qualquer solicitação SQL,
criar-se novas tabelas, base de dados (note que aı́ é necessário que se tenha permissão para
tal), assim como eliminá-las, fazer consultas, inserções, atualizações e etc. Além disso, pode-se
visualizar o banco de dados através de alguns comandos bem úteis:
1 SELECT F#, STATUS
2 FROM b o m f o r n e c e d o r
3 WHERE CIDADE = ’ Londres ’ ;
Código 12: Exemplo de uma consulta sobre uma VIEW.
1 CREATE VIEW t e s t e
2
AS SELECT #EMP, Nome Emp , S a l a r i o
3
FROM EMP
4
WHERE S a l a r i o > 3K ;
6 DELETE FROM t e s t e WHERE S a l a r i o < 5K ;
8 DELETE FROM EMP WHERE ( S a l a r i o > 3K && S a l a r i o < 5K ) ;
Código 13: Exemplo de eliminação de registro na VIEW e suas implicações na tabela real.
show databases; mostra todas as bases de dados do servidor que se tenha acesso. O comando
mysqlshow funciona da mesma forma só que este é executado no shell padrão, não no do
cliente.
use baseDeDadosX; configura a base de dados a ser utilizada. Normalmente, após a instalação, existem duas pré-definidas: mysql - que possui as permissões, usuários, etc. - e a
test - base para testes que qualquer usuário pode alterar.
show tables; mostra todas as tabelas da dase de dados configurada para uso. Note que antes é
necessário que se execute a instrução usebaseDeDadosX; . O comando mysqlshowbaseDeDadosX
funciona da mesma forma, mas é executado no shell padrão.
describe tabelaX; descreve como são cada campo de uma tabela, quais são seus tipos, seus
tamanhos, quais campos compõem a chave-primária, etc.
help mostra a ajuda.
Um outro comando, o mysqladmin, chama um programa diferente do cliente SQL. Esse
programa é usado para administrar vários aspectos do servidor de banco de dados MySQL.
Informações mais detalhadas a esse respeito podem ser obtidas em: http://dev.mysql.com/techresources/articles/mysql intro.html#SECTION0005000000.
Para finalizar, mostra-se abaixo dois exemplos de consultas SQL: a primeira executada na
prompt do cliente mysql, enquanto que a segunda é executada como um comando normal no
shell padrão.
• SELECT* FROM tabelaX;
• mysql-e ”SELECT * FROM tabelaX”baseDeDadosY
6
APIs - Application Program Interfaces
As APIs, ou Interfaces para Programas de Aplicação, permite que instruções SQL estejam
embutidas dentro de programas em linguagens comuns de programação, como C++, Java, PHP,
etc. Por isso mesmo, as APIs são também referenciadas como SQL Embutida.
Existem também referências para SQL Dinâmica, que nada mais é do que um conjunto
de recursos embutidos de SQL que se destinam a oferecer suporte à construção de aplicações
generalizadas, on-line e possivelmente interativas.
6.1
Java
Destinado ao fim anteriormente exposto, existe em Java um pacote chamado java.sql que permite executar as funcionalidades da SQL Embutida. Segundo a própria página de documentação
do pacote, “ele fornece uma API para acesso e processamento dos dados gravados em uma
fonte de dados (usualmente um banco de dados relacional) usando a linguagem de programação
JavaTM .” Para acessar essa página, basta seguir o ponteiro http://java.sun.com/j2se/1.4.2/docs/api/index.html.
Um exemplo interessante de como executar uma query em JavaTM é mostrado abaixo no código
[14]. O exemplo foi obtido do ponteiro http://www.ils.unc.edu/ lindgren/190/mysql-jdbc/.
Ele possui um inconveniente que é a utilização de um JDBC3 driver muito especı́fico - da Terrance Zellars - para a comunicação com o banco de dados. Um JDBC driver GPL fornecido pela
MySQL AB, e portanto mais confiável, é o MySQL Connector/J. Ele é o driver JDBC oficial para
o MySQL. Mais informações sobre o driver pode ser obtida em http://www.mysql.com/products/connector/j/.
Pode-se baixá-lo gratuitamente em http://dev.mysql.com/downloads/connector/j/3.0.html
6.2
C++
Programas escritos na linguagem C++ que necessitem das funcionalidades da SQL embutida
podem utilizar-se da API fornecida no ponteiro http://mysqlcppapi.sourceforge.net/.
Um exemplo da utilização dessa API pode ser observado no código [6.2] abaixo.
7
Estudo comparativo entre MySQL e PostgreSQL
Como dito na introdução desse documento, uma análise mais profunda comparando os bancos
de dados disponı́veis no mercado se faz bastante necessária. Principalmente entre os dois mais
comuns, MySQL [MySb] e PostgreSQL [Pos], e o considerado o mais eficiente, o Oracle [Ora].
Assim, apenas para ilustrar como a performance do MySQL, que foi a base deste documento,
é relativamente boa quando comparada com o Oracle 9i, mostra-se as figuras [6] e [7] abaixo.
Referências
[C. 00]
C. J. Date. Introdução a Sistemas de Bancos de Dados. Editora Campus, tradução da
sétima edição americana edition, 2000. 1, 4.1
[E. 72]
E. F. Codd. ”further normalization of the data base relational model”. Data Base
Systems, Courant Computer Science Symposia Series 6, 1972. 3.2
[MySa] Instalação do mysql. ’Internet’, http://dev.mysql.com/doc/#Installing. 1.1
[MySb] Mysql. ’Internet’, http://www.mysql.org/. 1.1, 7
[MyS04] MySQL
A.B.
MySQL
Reference
Manual.
MySQL
http://dev.mysql.com/get/Downloads/Manual/manualA.B,
a4.pdf/from/http://www.linorg.usp.br/mysql/, 1997-2004. 4.1
3
JDBC
(Java
Database
Connectivity),
de
acrodo
com
a
JavaSofts
em
http://www.javasoft.com/products/jdbc/overview.html, ”A API JDBC define classes Java para representar conexões com banco de bados, declarações SQL, etc..”
REFERÊNCIAS
19
Fonte: eWeek em ’Server Databases Clash’
Figura 6: Benchmark de banco de dados: páginas da web retornadas por segundo.
[Ora]
Oracle. ’Internet’, http://www.oracle.com/database/. 7
[Pos]
Postgresql. ’Internet’, http://www.postgresql.org/. 1.1, 7
REFERÊNCIAS
20
Fonte: eWeek em ’Server Databases Clash’
Figura 7: Benchmark de banco de dados: as respostas mais rápidas.
REFERÊNCIAS
21
1 import j a v a . s q l . ∗ ;
2 import twz1 . j d b c . mysql . ∗ ;
4 public c l a s s TestQuery {
6
7
public TestQuery ( ) {
}
9
public s t a t i c void main ( S t r i n g a r g s [ ] ) {
11
12
13
14
15
S t r i n g u r l=” j d b c : z1MySQL :
/ / l u n a . o i t . unc . edu /CES? u s e r=alexadmin ” ;
Connection con ;
S t r i n g query = ”SELECT ∗ FROM a l e x c o u r s e ” ;
Statement stmt ;
17
18
19
20
21
22
23
try {
C l a s s . forName ( ” twz1 . j d b c . mysql . j d b c M y s q l D r i v e r ” ) ;
}
catch ( j a v a . l a n g . ClassNotFoundException e ) {
System . e r r . p r i n t ( ” ClassNotFoundException : ” ) ;
System . e r r . p r i n t l n ( e . getMessage ( ) ) ;
}
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 }
try {
System . out . p r i n t l n ( ” Trying t o c o n n e c t . . . ” ) ;
con = DriverManager . g e t C o n n e c t i o n ( u r l , ” alexadmin ” , ”x” ) ;
System . out . p r i n t l n ( ” c o n n e c t e d ! ” ) ;
stmt = con . c r e a t e S t a t e m e n t ( ) ;
R e s u l t S e t r e s u l t = stmt . executeQuery ( query ) ;
while ( r e s u l t . next ( ) ) {
S t r i n g name = r e s u l t . g e t S t r i n g ( 1 )
+ ” ” + result . getString (2);
System . out . p r i n t l n ( name ) ;
}
stmt . c l o s e ( ) ;
con . c l o s e ( ) ;
}
catch ( SQLException ex ) {
System . e r r . p r i n t ( ” SQLException : ” ) ;
System . e r r . p r i n t l n ( ex . getMessage ( ) ) ;
}
}
Código 14: Exemplo de SQL Embutida com API para Java.
REFERÊNCIAS
22
1 #include < mysqlcppapi / mysqlcppapi . h>
2 #include < i o s t r e a m>
3 #include < iomanip>
5
6
7
8
9
10
11
12
13
14
15
int main ( ) {
// The f u l l fo r m a t f o r t h e Connection c o n s t r u c t o r i s
// Connection ( c c h a r ∗ db , c c h a r ∗ h o s t =””,
//
c c h a r ∗ u s e r =””, c c h a r ∗ passwd =””)
// You may need t o s p e c i f y some o f them i f t h e d a t a b a s e i s not on
// t h e l o c a l machine or your d a t a b a s e username i s not t h e same as
// your l o g i n name , e t c . .
try {
mysqlcppapi : : Connection con ;
con . c o n n e c t ( ) ;
con . s e l e c t d a t a b a s e ( ” m y s q l c p p d a t a ” ) ;
17
18
mysqlcppapi : : Query query = con . c r e a t e Q u e r y ( ) ;
// This c r e a t e s a q u e r y o b j e c t t h a t i s bound t o con .
20
21
22
query << ” s e l e c t ∗ from s t o c k ” ;
// You can w r i t e t o t h e q u e r y o b j e c t l i k e you would any o t h e r
// ostrem
24
25
mysqlcppapi : : R e s u l t S t o r e r e s = query . s t o r e ( ) ;
// Query : : s t o r e ( ) e x e c u t e s t h e q u e r y and r e t u r n s t h e r e s u l t s
27
28
29
c o u t << ” Query : ” << query . p r e v i e w () << e n d l ;
// Query : : p r e v i e w ( ) s i m p l y r e t u r n s a s t r i n g w i t h t h e c u r r e n t
// q u e r y s t r i n g i n i t .
31
c o u t << ” Records Found : ” << r e s . s i z e () << e n d l << e n d l ;
33
34
35
36
37
38
39
cout . s e t f ( i o s : : l e f t ) ;
c o u t << setw (17) << ” Item ”
<< setw ( 4 ) << ”Num”
<< setw ( 7 ) << ” Weight ”
<< setw ( 7 ) << ” P r i c e ”
<< ” Date ” << e n d l
<< e n d l ;
41
42
43
44
45
46
47
48
49
50
51
52
53
// The R e s u l t S t o r e c l a s s has a read−o n l y Random Access
// I t e r a t o r
f o r ( mysqlcppapi : : R e s u l t S t o r e : : i t e r a t o r i = r e s . b e g i n ( ) ;
i ! = r e s . end ( ) ; i ++)
{
mysqlcppapi : : Row row = ∗ i ;
c o u t << setw (17) << row [ 0 ]
<< setw ( 4 ) << row [ 1 ]
<< setw ( 7 ) << row [ ” w e i g h t ” ]
// you can use e i t h e r t h e i n d e x number or column
// name when r e t r i e v i n g t h e colume d a t a as
// d e m o n s t r a t e d above .
<< setw ( 7 ) << row [ 3 ]
REFERÊNCIAS
23
53
54
55
56
57
58
59
60
<< row [ 4 ] < < e n d l ;
}
}
catch ( mysqlcppapi : : ex BadQuery& e r )
{
// h a n d l e any c o n n e c t i o n or q u e r y e r r o r s t h a t may come up
c e r r << ” E r r o r : ” << e r . what () << e n d l ;
return − 1 ;
62
63
64
65
66
67
68
69
70
71
72
73 }
}
catch ( mysqlcppapi : : ex BadConversion & e r )
{
// we s t i l l need t o c a t c h bad c o n v e r s i o n s i n c a s e s o m e t h i n g
// g o e s wrong when t h e d a t a i s c o n v e r t e d i n t o s t o c k
c e r r << ” E r r o r : T r i e d t o c o n v e r t \” ”
<< e r . g e t D a t a () << ” \” t o a \” ”
<< e r . get TypeName () << ” \ ” . ” << e n d l ;
return − 1 ;
}
return 0 ;
Código 15: Exemplo de SQL Embutida com API para C++.
Download