Escolar Documentos
Profissional Documentos
Cultura Documentos
Apostila
BANCO DE DADOS II
2012
ÍNDICE
I.2.3. Tabela........................................................................................................................................................... 10
II.6. ROWS.......................................................................................................................................................................... 18
IV.1.1. GRANT.................................................................................................................................................... 28
VIII.2.2. NO-WAIT............................................................................................................................................... 52
ÍNDICE DE FIGURAS
INTRODUÇÃO
I.1. SGDB
O modelo relacional é um dos modelos mais utilizados e, apesar das recentes atualizações,
ainda é considerado um padrão para a maioria das aplicações em banco de dados.
A base da moderna tecnologia de banco de dados é, sem dúvida, o modelo
relacional: é essa base que faz da área uma ciência. (DATE, 2003, p. 93)
I.2.1. Esquema
I.2.3. Tabela
Uma tabela é, na verdade, uma matriz de linhas e colunas, onde as linhas também são
chamadas de registros e as colunas são chamadas de campos.
I.2.4. Relação
Uma relação r(R) é um conjunto de n-tuplas r = {t1, t2,..., tn}, onde cada n-tupla t é uma lista
ordenada de n valores t=(v1, v2,...,vn), sendo cada vi um elemento do dom(Ai) ou um valor
especial nulo.
I.2.5. Tupla
I.2.6. Domínio
I.2.7. Atributo
I.2.8. Chave-primária
São atributos que identificam registros em outras tabelas. A chave estrangeira (constraints key)
serve para representar uma tupla armazenada em outra tabela do mesmo banco de dados para
estabelecer uma restrição.
Uma chave única tem a função de impedir a duplicidade de atributos denominados chave
candidata, ou seja, que serve para identificar a tupla, mas não é chave primária.
Podemos dizer que toda chave primária é única mas nem toda chave única é primária.
Check constraint é uma chave que restringe ou valida os valores de um atributo. Geralmente
usada para definir domínio de usuário estático ou dinâmico.
Uma restrição estática sempre valida os mesmo valores enquanto que uma restrição dinâmica
valida conforme os valores de uma tabela ou seleção de registros.
11
I.2.12. Normalização
Normalização é um processo através do qual esquemas de relação, que não sejam satisfatórios
às características do modelo relacional, são decompostos em esquemas menores que satisfaçam
as propriedades desejáveis.
Na normalização, são analisadas algumas medidas de qualidade para o projeto de um esquema
de relação. Estas medidas de qualidade visam, por exemplo, evitar um mau uso da memória. As
medidas são as seguintes:
1 – correta representação semântica – os dados devem ser projetados de forma a terem seus
significados bem definidos e coerentes com o que realmente querem representar;
2 – reduções de valores redundantes – sempre que possível deve-se reduzir ao máximo os
valores redundantes desnecessários, ou seja, valores que muitas vezes aparecem repetidos
quando isto não seria preciso;
3 – reduções de valores nulos – sempre que possível deve-se reduzir o número de atributos
que por alguma razão receberão muitos valores nulos;
4 – evitar tuplas espúrias (sem sentido) – durante o processo de normalização deve-se atentar
para evitar que sejam geradas tuplas que não façam sentido diante da realidade, isto pode
ocorrer devido a alguma decomposição.
I.2.13. SQL
I.2.14. DDL
I.2.15. DCL
Subconjunto de comandos SQL destinado ao controle de acesso aos dados (Data Control
Language). Seus principais comandos são:
GRANT – Para atribuir direitos
REVOKE – Para revogar direitos
Os comandos DCL são considerados por muitos como comandos de manipulação (DDL).
12
I.2.16. DML
I.2.17. Metadata
Metadados ou Metainformação são dados capazes de descrever outros dados, ou seja, dar um
significado real e plausível a um arquivo de dados, são a representação de um objeto digital.
Dicionário de dados é um grupo de tabelas, habilitadas apenas para leitura ou consulta, ou seja,
é uma base de dados, que entre outras coisas, mantém as seguintes informações:
• Definição precisa sobre elementos de dados
• Perfis de usuários, papéis e privilégios.
• Descrição de objetos
• Integridade de restrições
• Stored procedures e gatilhos
• Estrutura geral da base de dados
• Informação de verificação
• Alocações de espaço
Notação usada no dicionário de dados:
Símbolo Significado
= Constituído por ou definido por
+ E (conjunção ou concatenação)
() Componentes opcionais
[] Componentes alternados
| Separador de componentes alternáveis [ ]
{} Componentes repetidos ou não
** Comentários
@ Chave primária
Exemplos:
Nome = tratamento + primeiro_nome + ultimo_nome
Cortesia = [Sr|Sra|Prof|Dr]
Caracter = [A-Z|a-z| | -]
Descrição = {Caracter}
I.2.19. Catálogo de dados
MySql – Gratuito, rápido e muito utilizado em aplicações WEB e projetos WEB opensource.
PostGreSQL – Gratuito, poderoso e muito conceitual.
Firebird – Originado do Interbase, gratuito, muito disseminado no Brasil.
Oracle – Considerado por muitos o banco de dados ideal para grandes corporações, é pago,
possui muitas soluções integradas e é mutiplataforma.
MS SQL – É pago, ideal para aplicações de médio e grande porte. Usado preferencialmente para
integrar soluções Microsoft. Não é multiplataforma.
I.4. ATIVIDADES I
Questão 1.1: Crie um banco de dados com o nome CLUBE.fdb com a seguinte estrutura:
Figura 1 – Clube.fdb
Questão 1.2: Defina os campos chaves e a integridade referencial envolvendo todas as tabelas
do banco de dados:
15
16
II.1. JOINS
De acordo com (CANTU, 2006) faz relacionamento de diversas formas entre diversas tabelas em
um mesmo comando select.
A sintaxe da cláusula JOIN precisa incluir a palavra reservada ON que estabelece a regra da
relação. Chamamos de stream as informações vindas de cada tabela.
Também chamado de exclusive join (junção exclusiva) faz o relacionamento entre os streams de
acordo com a expressão da cláusula ON, ignorando registros que não satisfaçam a condição.
A palavra JOIN é opção, ou seja, terá o mesmo efeito se for usada ou não.
Exemplo:
SELECT S.SOC_ID,S.SOC_NOME, C.COT_VALIDADE
FROM SOCIOS S
INNER JOIN COTAS C ON S.SOC_COTA = C.COT_ID
Uma junção do tipo OUTER irá retornar, inclusive, os registros que não satisfazem a condição da
expressão do stream esquerdo ou direito de acordo com a sintaxe escolhida.
LEFT: Retorna todas as linhas do stream esquerdo.
RIGHT: Retorna todas as linhas do stream direito.
FULL: Retorna todos registros do stream esquerdo e todos do stream direito. Os campos cujo o
registro não satisfaz condição da expressão é representado por NULL.
Exemplo:
SELECT S.SOC_NOME,C.COT_VALIDADE
FROM SOCIOS S
LEFT JOIN COTAS C ON S.SOC_COTA = C.COT_ID
Neste caso, mesmo que não exista na tabela de contas um registro correspondente ao sócio, o
nome dele irá aparecer no stream e o campo COT_VALIDADE irá apresentar o valor NULL.
II.1.3. CROSSJOIN
II.2. UNION
A função do UNION é unir os registros do select anterior aos registros do segundo select.
Um bom exemplo do uso de UNION seria para gerar um conjunto de registros de pessoas
físicas e jurídicas armazenados em tabelas diferentes.
SELECT NOME FROM PESSOA_FISICA
UNION
SELECT NOME FROM PESSOA_JURIDICA
Neste caso os nomes que ocorrerem nas duas tabelas serão apresentados sem repetição.
Para exibir todos os registros é preciso adicionar a palavra ALL na frente de UNION (Union all).
O número de colunas de cada select deve ser igual, bem como, o tipo de cada coluna.
Recomenda-se o uso de funções de conversão (CAST) para adequar a esta restrição do UNION.
Segundo (CANTU, 2006), SELECT FROM SELECT também chamado de recurso de tabelas
derivadas e está previsto no padrão ANSI SQL.
Este recurso permite a elaboração de consultas mais complexas sem ter que usar views ou
stored procedures.
Exemplo:
SELECT FIRST 10 AVG(NF.TOTAL)
FROM (
SELECT F1.TOTAL FROM FILIAL1 F1
UNION ALL
SELECT F2.TOTAL
FROM FILIAL2 F2
ORDER BY 1 DESC) AS NF
II.4. FIRST
Define quantos registros serão recuperados pelo select, mesmo que existam outros que
satisfaçam aos critérios.
Exemplo:
SELECT FIRST 10 S.SOC_ID, SOC_NOME
FROM SOCIOS S
WHERE UPPER(S.SOC_NOME) CONTAINING ‘SILVA’
Retorna apenas os 10 primeiros registros que atendem aos critérios, ou seja, com a palavra silva
no nome.
II.5. SKIP
Define quantos registros iniciais serão ignorados pelo select antes de começar a retornar dados.
Exemplo:
SELECT FIRST 10 SKIP 5 S.SOC_ID, SOC_NOME
FROM SOCIOS S
WHERE UPPER(S.SOC_NOME) STARTING WITH ‘A’
Os 5 primeiros registros serão ignorados e depois serão retornados os próximos 10.
18
II.6. ROWS
Define o intervalo de registros que serão retornados com o objetivo de limitar o número de
registros.
Exemplo:
SELECT S.SOC_ID,SOC_NOME
FROM SOCIOS S
WHERE UPPER(S.SOC_NOME) LIKE ‘%SILVA%’
ROWS 10
Retorna apenas os 10 primeiros registros que atendem aos critérios, ou seja, com a palavra silva
no nome. Mesmo efeito que a cláusula SKIP.
II.7. CONCATENAÇÃO
Exemplo:
SELECT NOME || ‘ ‘ || SOBRENOME FROM CLIENTES
II.8. ATIVIDADE II
Passo1: Descreva uma situação onde é preciso utilizar SELECT from SELECT para resolver.
19
III.1. ÍNDICES
De acordo com Elmasri e Novate (2011), Índices são estruturas de acesso adicionais auxiliares
usadas para aumentar a velocidade da recuperação de registros na resposta a certas condições
de busca.
Quando uma relação não possui índices definidos, o SGBD deve percorrer toda a relação para
localizar os dados desejados. Isso pode demorar muito, mas quando há índices, a busca é
facilitada pelo endereçamento dos dados armazenados.
O uso de índices deve ser regrado, pois, a criação, manutenção e atualização dos índices
demandam recursos de processamento e seu uso sem critérios pode levar a perda de
desempenho ou aumento desnecessário do volume armazenado.
Elmasri e Novate (2011), classificam os índices em:
É um arquivo ordenado em que os registros são de tamanho fixo e contêm dois campos:
Chave primária: É o conteúdo do mesmo tipo do atributo do registro indexado
Ponteiro: É o ponteiro para o bloco do disco onde o registro se encontra.
Representação: <K(i), P(i)>
Exemplo:
<K(1) = (Pedro), P(1) = endereço do bloco 1>
<K(1) = (João), P(2) = endereço do bloco 1>
<K(1) = (Ana), P(2) = endereço do bloco 2>
Chamamos de índice esparso quando os valores indexados nunca se repetem ou repetem
poucas vezes. Denso quando há várias ocorrências do mesmo valor.
O maior problema deste tipo de índice é o trabalho necessário para incluir e excluir registros, ou
seja, será preciso realizar a ordenação do índice.
Também é um arquivo ordenado e com dois campos, assim como, o índice primário, porém, ao
invés de armazenar a chave primária, armazena um campo que não é chave, logo, há repetições
dos valores, por isto é chamado de agrupamento.
Também é considerado esparso porque para cada registro haverá uma entrada no índice,
ocasionando a repetição.
O problema da inclusão no índice de agrupamento é amenizado reservando-se um bloco inteiro
ou um conjunto de blocos adjacentes para cada valor do campo de clustering.
20
Um índice secundário fornece um acesso secundário para um arquivo que já possui acesso
primário. Geralmente usado para campo que é chave candidata e possui valor único para cada
registro com repetição permitida.
Também possui dois campos, porém o segundo nem sempre é o bloco do arquivo, podendo ser
uma chave do índice primário.
Também é classificado como índice denso.
Os índices baseados em árvore são usados geralmente para pesquisar intervalos de valores, mas
servem também para pesquisas com operador de igualdade.
Dentre as estruturas em árvore, B+ é a mais usadas pelos SGDBs. Um de seus pontos fortes é o
fato de ser uma estrutura dinâmica.
Exemplo de uma estrutura B+:
Figura 3 – índice B+
Índice multinível:
Para aumentar o desempenho da busca em arquivos muito grandes os
arquivos ordenados (arquivos de índice) possuem seus arquivos
ordenados conforme a necessidade. Estes diversos níveis possíveis são
implementados usando técnicas avançadas para facilitar as inclusões e
exclusões. Quando há uma reserva de entradas para os níveis do índice
dissemos que são índices multiníveis dinâmicos. Exemplos: B-tree e
B-tree+.
21
A criação de índices na maioria dos servidores de banco de dados está implicitamente associada
à criação de chaves (Primária, estrangeira e única).
Isto quer dizer que quando executamos o comando ALTER TABLE para adicionar uma chave,
automaticamente um índice é criado pelo SGDB.
Quando queremos forçar a criação de um índice para um campo que teremos muitas consultas
usamos a seguinte sintaxe:
Para criar índices secundários:
CREATE INDEX [NOME_INDICE] ON [TABELA] ([CAMPO])
Exemplo de criação:
CREATE INDEX T_CLIENTES_IDX1 ON T_CLIENTES (T_CLIENTES_NOME)
Exemplo de exclusão:
DROP INDEX T_CLIENTES_IDX1
O Firebird suporta somente um tipo de índice: uma variação do b-tree. Índices podem ser
únicos ou permitir duplicidades; Eles podem ter uma chave simples ou composta, ascendente
ou descendente.
Para recomputador um índice:
SET STATISTICS INDEX [NOME_INDICE]
Para desativar um índice:
ALTER INDEX [NOME_INDICE] INACTIVE
Para ativar um índice:
ALTER INDEX [NOME_INDICE] ACTIVE
Sintaxe para Firebird 2.5:
CREATE [UNIQUE] [ASC[ENDING] | [DESC[ENDING]] INDEX indexname
ON tablename
{ (<col> [, <col> ...]) | COMPUTED BY (expression) }
<col> ::= a column not of type ARRAY, BLOB or COMPUTED BY
Exemplo:
create descending index ix_events_yt
on MyEvents
computed by (extract(year from StartDate) || Town);
III.2. FUNÇÕES
As funções internas não precisam de nenhum procedimento extra para funcionar, porque já são
disponibilizadas automaticamente quando instalamos o servidor. Na maioria dos bancos de
22
dados, encontramos todas as funções mais comuns. Mas há bancos com funções específicas,
tornando obrigatória a consulta aos manuais de referência.
Até a versão 2.0 do Firebird as seguintes funções internas estavam disponíveis:
Função Descrição ANSI SQL
SUM Retorna a soma de um campo ou expressão de todas as tuplas ANSI
percorridas.
Sintaxe: SUM(arg1)
MAX Retorna o valor máximo de um campo ou expressão encontrado nas ANSI
tuplas percorridas.
Sintaxe: MAX (arg1)
MIN Retorna o valor mínimo de um campo ou expressão encontrado nas ANSI
tuplas percorridas.
Sintaxe: MIN (arg1)
AVG Retorna a média de um campo ou expressão de todas as tuplas ANSI
percorridas.
Sintaxe: AVG(arg1)
COUNT Retorna a contagem dos registros do select de acordo com a cláusula ANSI
group by
IIF Retorna um dos valores possíveis de acordo com o resultado da INTERBASE/
avaliação de uma expressão lógica. FIREBIRD
Sintaxe: IIF (<Condição>, <valor1>, <valor2>)
NULLIF Retorna NULL se um dos valores (valor1, valor2) forem iguais ou valor1 INTERBASE/
se forem diferentes. FIREBIRD
Sintaxe: NULLIF(valor1, valor2)
COALEASE Retornar o primeiro valor não nulo de uma seqüência de valores. INTERBASE/
Sintaxe: Coalease(valor1, valor2,valor3,...) FIREBIRD
CAST Conte uma informação de um determinado tipo em outro tipo. ANSI
Sintaxe: CAST (arg1 as tipo)
EXTRACT Extrai elementos individuais de um campo Data/Hora. ANSI
YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, WEEKDAY, YEARDAY.
Sintaxe: EXTRACT (parte from valor)
Exemplo: EXTRACT(YEAR FROM DATA_EMISSAO)
SUBSTRING Retorna parte de uma String. ANSI
Sintaxe: SUBSTRING(arg1 FROM início [FOR tamanho])
UPPER Converte uma String em letras maiúsculas. ANSI
Sintaxe: UPPER(arg1)
LOWER Converte uma String em letras minículas. ANSI
Sintaxe: LOWER(arg1)
TRIM Remove a ocorrência de espaço ou um determinado caractere ANSI
especificado do início, fim ou ambos de uma String.
Sintaxe: TRIM([[{leading|trailing|both}] [arg1] FROM ] arg2)
GEN_ID Recupera o valor de um GENERATOR. INTERBASE/
Sintaxe: GEN_ID(nome_do_generator, incremento) FIREBIRD
A partir da versão 2.5, foram incluídas muitas outras funções listadas a seguir:
ABS (number)
ACOS (number)
ASCII_CHAR (<code>) - code> ::= an integer in the range [0..255]
ASCII_VAL (ch) - ch ::= a [VAR]CHAR or text BLOB of max. 32767 bytes
ASIN (number)
ATAN (number)
23
ATAN2 (y, x)
BIN_AND (number [, number ...])
BIN_OR (number [, number ...])
BIN_SHL (number, shift)
BIN_SHR (number, shift)
BIN_XOR (number [, number ...])
BIT_LENGTH (str)
CAST (expression AS <target_type>)
CEIL[ING] (number)
CHAR_LENGTH (str)
CHARACTER_LENGTH (str)
CHAR_TO_UUID (ascii_uuid)
COALESCE (<exp1>, <exp2> [, <expN> ... ])
COS (angle)
COSH (number)
COT (angle)
DATEADD (<args>)
DATEDIFF (<args>)
DECODE ( <test-expr>, <expr>, result [, <expr>, result ...] [, defaultresult] )
EXP (number)
EXTRACT (<part> FROM <datetime>) <part> ::= YEAR | MONTH | WEEK | DAY |
WEEKDAY | YEARDAY | HOUR | MINUTE | SECOND | MILLISECOND <datetime> ::=
a DATE, TIME or TIMESTAMP expression
FLOOR (number)
GEN_ID (generator-name, <step>) <step> ::= An integer expression.
GEN_UUID ()
HASH (string)
IIF (<condition>, ResultT, ResultF)<condition> ::= A boolean expression.
LEFT (string, length)
LN (number)
LOG (x, y)
LOG10 (number)
LOWER (str)
LPAD (str, endlen [, padstr])
MAXVALUE (expr [, expr ...])
MINVALUE (expr [, expr ...])
MOD (a, b)
NULLIF (<exp1>, <exp2>)
OCTET_LENGTH (str)
OVERLAY (string PLACING replacement FROM pos [FOR length])
PI ()
24
Apesar de já existirem diversas funções previstas pelo padrão ANSI SQL, muitos servidores de
banco de dados possuem suas próprias funções ou não seguem a mesma sintaxe e nome das
funções padronizadas.
Alguns servidores permitem a criação de funções de usuário diretamente em um editor de
código incorporado ao gerenciador.
No caso do INTERBASE/FIREBIRD há poucas funções nativas, mas podemos facilmente adicionar
novas funções disponíveis na Internet, compiladas conforme o sistema operacional.
Para incluir novas funções no Firebird é preciso baixar o arquivo de funções (.DLL) e coloca-lo na
pasta UDF, criada pelo instalador.
Antes de usar a função é preciso realizar a sua declaração.
Veja no exemplo abaixo o comando de declaração de uma função de usuário do Firebird:
DECLARE EXTERNAL FUNCTION UDF_LEN
CSTRING(254)
RETURNS INTEGER BY VALUE
ENTRY_POINT 'udf_Len' MODULE_NAME 'tbudf';
Esta função fica armazenada no arquivo tbudf.dll (Windows) ou tfudf.so (Linux). Serve para
retornar o tamanho de um conteúdo String.
Exemplo de utilização da função declarada acima:
SELECT NOME, UDF_LEN(NOME) AS TAMANHO FROM CLIENTES.
III.3. GROUP BY
A cláusula GROUP BY define os campos que serão agrupados quando se quer usar funções de
agrupamento.
Exemplo:
SELECT CAT.CAT_DESCRICAO,COUNT(*) AS QTD
FROM SOCIOS S
INNER JOIN COTAS C ON S.SOC_COTA = C.COT_ID
INNER JOIN CATEGORIAS CAT ON CAT.CAT_ID = C.COT_CATEG
GROUP BY CAT.CAT_DESCRICAO
ORDER BY CAT.CAT_DESCRICAO
III.3.1. HAVING
Podemos dizer que HAVING é uma restrição assim como WHERE, porém, aplicável ao resultado
do agrupamento.
Exemplo:
SELECT CAT.CAT_DESCRICAO,COUNT(*) AS QTD
FROM SOCIOS S
INNER JOIN COTAS C ON S.SOC_COTA = C.COT_ID
INNER JOIN CATEGORIAS CAT ON CAT.CAT_ID = C.COT_CATEG
GROUP BY CAT.CAT_DESCRICAO
HAVING COUNT(*) > 1
ORDER BY CAT.CAT_DESCRICAO
Neste caso, apenas os registros cujo resultado da função de agrupamento COUNT(*) for maior
que 1, serão exibidos. Não seria possível obter o mesmo resultado apenas usando a cláusula
WHERE.
26
Questão 3.2: Informe o comando SQL que conta o número de sócios cadastrados agrupando
por descrição da cota:
Questão 3.3: Informe o comando SQL que soma o débito de sócios cadastrados agrupando por
mês/ano:
28
UNIDADE IV.SEGURANÇA
Uma das principais propriedades de um SGDB é realizar o controle de acesso aos dados para
permitir que os usuários acessem apenas as informações que o administrador planejou.
IV.1.1. GRANT
Sintaxe:
GRANT { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER }
[,...] | ALL [ PRIVILEGES ] }
ON [ TABLE ] nome_da_tabela [, ...]
TO { nome_do_usuário | GROUP nome_do_grupo | PUBLIC } [, ...] [ WITH GRANT OPTION ]
O comando GRANT concede privilégios específicos para um objeto (tabela, visão, seqüência,
banco de dados, função, linguagem procedural, esquema ou espaço de tabelas) para um ou
mais usuários ou grupos de usuários. Estes privilégios são adicionados aos já concedidos, se
existirem.
A palavra chave PUBLIC indica que os privilégios devem ser concedido para todos os usuários,
inclusive aos que vierem a ser criados posteriormente. PUBLIC pode ser considerado como um
grupo definido implicitamente que sempre inclui todos os usuários. Um determinado usuário
possui a soma dos privilégios concedidos diretamente para o mesmo, mais os privilégios
29
concedidos para todos os grupos que este seja membro, mais os privilégios concedidos para
PUBLIC.
Se for especificado WITH GRANT OPTION quem receber o privilégio poderá, por sua vez,
conceder o privilégio a terceiros. Sem a opção de concessão, quem recebe não pode conceder o
privilégio. Atualmente as opções de concessão somente podem ser concedidas a usuários
individuais, e não a grupos ou PUBLIC.
Não é necessário conceder privilégios para o dono do objeto (geralmente o usuário que o
criou), porque o dono possui todos os privilégios por padrão (Entretanto, o dono pode decidir
revogar alguns de seus próprios privilégios por motivo de segurança). O direito de remover um
objeto, ou de alterar a sua definição de alguma forma, não é descrito por um privilégio que
possa ser concedido; é inerente ao dono e não pode ser concedido ou revogado. O dono possui
também, implicitamente, todas as opções de concessão para o objeto.
Dependendo do tipo do objeto, os privilégios padrão iniciais podem incluir a concessão de
alguns privilégios para PUBLIC. O padrão é: não permitir o acesso público às tabelas, esquemas
e espaços de tabelas; para os bancos de dados conceder o privilégio CONNECT e o privilégio de
criação de tabela TEMP; para as funções conceder o privilégio EXECUTE; e para as linguagens
conceder o privilégio USAGE. O dono do objeto poderá, é claro, revogar estes privilégios (para a
máxima segurança o comando REVOKE deverá ser executado na mesma transação que criar o
objeto; dessa forma não haverá espaço de tempo para outro usuário utilizar o objeto).
Os privilégios possíveis são:
SELECT - Permite consultar (SELECT) qualquer coluna da tabela, visão ou seqüência
especificada. Também permite utilizar o comando COPY TO. Para as seqüências, este privilégio
também permite o uso da função currval.
INSERT - Permite inserir (INSERT) novas linhas na tabela especificada. Também permite utilizar
o comando COPY FROM.
UPDATE - Permite modificar (UPDATE) os dados de qualquer coluna da tabela especificada. O
comando SELECT ... FOR UPDATE também requer este privilégio (além do privilégio SELECT).
DELETE - Permite excluir (DELETE) linhas da tabela especificada.
RULE - Permite criar regras para a tabela ou para a visão.
REFERENCES - Para criar uma restrição de chave estrangeira é necessário possuir este privilégio,
tanto na tabela que faz referência quanto na tabela que é referenciada.
TRIGGER - Permite criar gatilhos na tabela especificada.
CREATE - Para bancos de dados, permite a criação de novos esquemas no banco de dados.
Para esquemas, permite a criação de novos objetos no esquema. Para mudar o nome de um
objeto existente é necessário ser o dono do objeto e possuir este privilégio no esquema que o
contém.
Para espaços de tabelas, permite a criação de tabelas e índices no espaço de tabelas, e permite
a criação de bancos de dados possuindo este espaço de tabelas como seu espaço de tabelas
padrão (Deve ser observado que revogar este privilégio não altera a colocação dos objetos
existentes).
TEMPORARY - TEMP - Permite a criação de tabelas temporárias ao usar o banco de dados.
EXECUTE - Permite utilizar a função especificada e qualquer operador implementado utilizando
a função. Este é o único tipo de privilégio aplicável às funções (Esta sintaxe funciona para as
funções de agregação também).
30
USAGE - Para as linguagens procedurais, permite o uso da linguagem especificada para criar
funções nesta linguagem. Este é o único tipo de privilégio aplicável às linguagens procedurais.
Para os esquemas, permite acessar os objetos contidos no esquema especificado (assumindo
que os privilégios requeridos para os próprios objetos estejam atendidos). Essencialmente,
concede a quem recebe o direito de "procurar" por objetos dentro do esquema.
ALL PRIVILEGES - Concede todos os privilégios disponíveis de uma só vez.
Os privilégios requeridos por outros comandos estão listados nas páginas de referência dos
respectivos comandos.
Exemplos:
GRANT SELECT, UPDATE ON CATEGORIAS TO ADM;
GRANT ALL PRIVILEGES ON CONFIG TO ADM;
IV.1.2. REVOKE
Sintaxe:
REVOKE [ GRANT OPTION FOR ] privilégios
ON objeto [ ( coluna [, ...] ) ]
FROM { PUBLIC | nome_do_usuário [, ...] }
{ RESTRICT | CASCADE }
O comando REVOKE revoga, um ou mais papéis, privilégios concedidos anteriormente. A
palavra chave PUBLIC se refere ao grupo contendo todos os usuários, definido implicitamente.
Deve ser observado que um determinado papel possui a soma dos privilégios concedidos
diretamente para o próprio papel, mais os privilégios concedidos para os papéis dos quais o
papel é membro no momento, mais os privilégios concedidos para PUBLIC. Daí, por exemplo,
revogar o privilégio SELECT de PUBLIC não significa, necessariamente, que todos os papéis
perderão o privilégio SELECT para o objeto: os papéis que receberam o privilégio diretamente,
ou através de outro papel, ainda terão o privilégio.
Se for especificado GRANT OPTION FOR somente a opção de concessão do privilégio é
revogada, e não o próprio privilégio. Caso contrário, tanto o privilégio quanto a opção de
concessão serão revogados.
Se o usuário possui um privilégio com opção de concessão, e concedeu este privilégio para
outros usuários, então os privilégios que estes outros usuários possuem são chamados de
privilégios dependentes. Se o privilégio ou a opção de concessão que o primeiro usuário possui
for revogada, e existirem privilégios dependentes, estes privilégios dependentes também serão
revogados se for especificado CASCADE, senão a ação de revogar falhará. Esta revogação
recursiva somente afeta os privilégios que foram concedidos através de uma cadeia de usuários
começando pelo usuário objeto deste comando REVOKE. Portanto, os usuários afetados
poderão manter o privilégio, se o privilégio também tiver sido concedido por outros usuários.
Ao revogar o privilégio de membro de um papel, GRANT OPTION passa a se chamar ADMIN
OPTION, mas o comportamento é semelhante.
Um determinado usuário pode revogar somente os privilégios que foram concedidos
diretamente por este usuário. Se, por exemplo, o usuário A concedeu um privilégio com opção
de concessão para o usuário B, e o usuário B por sua vez concedeu o privilégio para o usuário C,
então o usuário A não poderá revogar diretamente o privilégio de C. Em vez disso, o usuário A
poderá revogar a opção de concessão do usuário B usando a opção CASCADE, para que o
privilégio seja, por sua vez, revogado do usuário C. Outro exemplo é o caso em que tanto A
quanto B concederam o mesmo privilégio a C: neste caso A poderá revogar sua própria
31
concessão, mas não poderá revogar a concessão feita por B e, portanto, C continuará com o
privilégio mesmo que A revogue o privilégio.
Se alguém que não for dono do objeto tentar revogar privilégios sobre o objeto, o comando
falhará inteiramente caso o usuário não possua ao menos um privilégio para o objeto. Se o
usuário possuir algum privilégio para o objeto o comando prosseguirá, mas só revogará os
privilégios para os quais o usuário tem a opção de concessão. A forma REVOKE ALL PRIVILEGES
emite uma mensagem de advertência quando o usuário não possui ao menos uma opção de
concessão, enquanto as outras formas emitem uma mensagem de advertência quando o
usuário não possui opção de concessão para algum dos privilégios especificamente
identificados no comando (Em princípio estas informações também se aplicam ao dono do
objeto, mas como o dono é sempre tratado como possuindo todas as opções de concessão
estes casos nunca ocorrem).
Se um superusuário decidir submeter o comando GRANT ou REVOKE, o comando será
executado como se tivesse sido submetido pelo dono do objeto afetado. Uma vez que todos os
privilégios partem do dono do objeto (possivelmente de forma indireta através de cadeias de
opções de concessão), um superusuário pode revogar todos os privilégios, mas pode ser
necessário usar CASCADE conforme mostrado acima.
O comando REVOKE também pode ser submetido por um papel que não é o dono do objeto
afetado, mas é membro do papel que é dono do objeto, ou é um membro de um papel que
possui privilégios com WITH GRANT OPTION no objeto. Neste caso, o comando será executado
como se tivesse sido emitido pelo papel que realmente possui o objeto ou possui privilégios
com WITH GRANT OPTION. Por exemplo, se a tabela t1 pertencer ao papel g1, do qual o papel
u1 é membro, então u1 poderá revogar privilégios sobre t1 registrados como tendo sido
concedidos por g1. Isto inclui concessões feitas por u1 assim como por qualquer outro membro
do papel g1.
Se o papel que está executando o comando REVOKE possuir os privilégios requeridos
indiretamente, através de um caminho de membro de mais de um papel, é incerto qual dos
papéis será registrado como tendo executado o comando. Nestes casos, a melhor prática é
utilizar o comando SET ROLE para assumir o papel específico com o qual se deseja executar o
comando REVOKE. Caso isto não seja feito, poderá resultar na revogação de privilégios além
dos pretendidos, ou até em não revogar nada.
Exemplos:
Revogar o privilégio de inserção na tabela socios concedido para o usuário ADM:
REVOKE INSERT ON SOCIOS FROM ADM;
O utilitário nativo do Firebird para manutenção de usuários é o GSEC que pode ser usado em
linha de comando ou interativamente.
Roteiro de exemplo para criar um usuário (mhs – Márcio Henrique Silva):
- Execute o prompt de comando (cmd ou command)
- Entre na pasta "c:\arquivos de programas\firebird\firebird_2_1\bin"
- Digite: gsec -user SYSDBA -password masterkey <Enter>
- No prompt "GSEC>" digite: display <Enter> (para ver os usuários cadastrados)
- Criando o usuário: add mhs -pw 123 -fmarcio -mName Henrique -lName Silva;
Para modificar a senha do SYSDBA no GSEC:
32
IV.2. ATIVIDADE IV
Passo 2: Crie um usuário chamando ADM com a senha 123, LEITOR com a senha 456 e saia do
GSEC.
Informe aqui os comandos que devem ser usados:
Passo 6: Dê permissão para a tabela SOCIOS com GRANT OPTION para a role GERENTES .
Informe aqui o comando que deve ser usado:
Passo 7: Tente Acesse o banco com o usuário LEITOR e tente modificar a tabela SOCIOS.
Informe a mensagem apresentada pelo servidor.
34
Sintaxe:
CREATE PROCEDURE NomedaProcedure
<parâmetros de entrada>
RETURNS
<parâmetros de saída>
AS
<declaração de variáveis locais>
BEGIN
<comandos da procedures>
END
V.1.2. Parâmetros
Parâmetros de entrada: Permite à aplicação cliente passar os valores que serão usados para
modificar o comportamento da SP.
Parâmetros de saída ou de retorno: São informações retornadas para a aplicação cliente.
Obs: Um parâmetro pode ser de qualquer tipo de dados do Firebird exceto BLOB ou ARRAY.
CREATE PROCEDURE SUB_TOT_BUDGET(
HEAD_DEPT CHAR(3))
RETURNS (
TOT_BUDGET NUMERIC (15, 2),
AVG_BUDGET NUMERIC (15, 2),
MIN_BUDGET NUMERIC (15, 2),
MAX_BUDGET NUMERIC (15, 2))
AS
BEGIN
SELECT SUM(BUDGET),
AVG(budget), MIN(budget), MAX(budget)
FROM department
WHERE head_dept = :head_dept
INTO :tot_budget, :avg_budget, :min_budget, :max_budget;
SUSPEND;
END ^
35
Esta SP declara um parâmetro de entrada, HEAD_DEPT cujo tipo é CHAR(3) e quatro parâmetros
de saída, TOT_BUDGET, AVG_BUDGET, MIN_BUDGET, e MAX_BUDGET todos do tipo
NUMERIC(15, 2). Tanto os parâmetros de entrada quando os de saída devem estar entre
parênteses. O comando SUSPEND pausa a SP até que o cliente busque os valores dos
parâmetros de saída.
É possível declarar variáveis locais de qualquer tipo suportado pelo Firebird dentro de uma SP.
Estas variáveis só existem enquanto a SP está sendo executada e seu escopo é local. Variáveis
locais são declaradas depois da palavra chave AS e antes da palavra chave BEGIN que identifica
o início do corpo da SP. Para declarar variáveis use:
DECLARE VARIABLE <Nome variável> <Tipo variável>
DECLARE VARIABLE OrderCount Integer;
DECLARE VARIABLE TotalAmount NUMERIC(15,2);
Note que cada comando DECLARE VARIABLE só pode declarar uma variável. A SP a seguir ilustra
o uso do comando DECLARE VARIABLE. Ela declara quatro variáveis locais , ord_stat, hold_stat,
cust_no and any_po. Observe que quando uma variável é usada na cláusula INTO de um
comando SELECT um sinal de dois pontos ':' deve anteceder o nome da variável.
CREATE PROCEDURE SHIP_ORDER(
PO_NUM CHAR(8))
AS
DECLARE VARIABLE ord_stat CHAR(7);
DECLARE VARIABLE hold_stat CHAR(1);
DECLARE VARIABLE cust_no INTEGER;
DECLARE VARIABLE any_po CHAR(8);
BEGIN
SELECT s.order_status, c.on_hold, c.cust_no
FROM sales s, customer c
WHERE po_number = :po_num
AND s.cust_no = c.cust_no
INTO :ord_stat, :hold_stat, :cust_no;
/*
* Se existe uma conta não paga de pedidos enviados a mais de 2 meses,
* passe o cliente para cliente em atraso.
*/
FOR SELECT po_number
FROM sales
WHERE cust_no = :cust_no
AND order_status = 'shipped'
AND paid = 'n'
AND ship_date < CAST('NOW' AS DATE) - 60
INTO :any_po
DO
BEGIN
EXCEPTION customer_check;
UPDATE customer
SET on_hold = '*'
36
ELSE
<comando>
Onde <comando> pode ser tanto um comando simples quanto um bloco de comandos
delimitado por um BEGIN-END. Na <expressão condicional> além dos operadores lógicos
normais (=, <, >, <=, >=, <>) pode-se usar também os seguintes operadores SQL:
Exemplos de comandos IF válidos são:
IF (any_sales > 0) THEN
BEGIN
EXCEPTION reassign_sales;
SUSPEND;
END
IF (first IS NOT NULL) THEN
line2=first || ' ' || last;
ELSE
line2=last;
Note no exemplo acima que na linguagem do Firebird o operador de concatenação de strings é
|| (Duas barras verticais) e não o + como acontece na maioria das linguagens de programação.
IF (:mngr_no IS NULL) THEN
BEGIN
mngr_name='--TBH--';
title='';
END
ELSE
SELECT full_name, job_code
FROM employee
WHERE emp_no=:mngr_no
INTO :mngr_name, :title;
WHILE-DO
A estrutura WHILE-DO permite criar loops nas stored procedures e triggers. A sintaxe é:
WHILE (<expressão condicional) DO <comando>
Onde <comando> pode ser um bloco de comandos delimitado por um par BEGIN-END.
Observe que a expressão condicional tem que estar entre parênteses.
WHILE (i <=5) DO
BEGIN
SELECT language_req[:i] FROM job
WHERE ((job_code=:code) AND (job_grade=:grade) AND (job_country=:cty)
AND (language_req IS NOT NULL))
INTO :languages;
IF (languages=' ')THEN /* Imprime 'NULL' ao invés de espaços */
languages='NULL';
i=i +1;
SUSPEND;
END
É possível usar os comandos SQL SELECT, INSERT, UPDATE e DELETE em uma SP exatamente
como se faz em uma query, apenas com algumas pequenas alterações na sintaxe. Para todos
esses comandos pode-se usar variáveis locais ou parâmetros de entrada em qualquer lugar que
um valor literal seria aceito. Por exemplo, no comando INSERT, a seguir, os valores inseridos são
obtidos de um parâmetro de entrada.
CREATE PROCEDURE ADD_EMP_PROJ(
EMP_NO SMALLINT,
PROJ_ID CHAR(5) )
AS
BEGIN
INSERT INTO employee_project (emp_no, proj_id) VALUES (:emp_no,
:proj_id);
WHEN SQLCODE -530 DO
EXCEPTION unknown_emp_id;
38
END
SUSPEND;
END ^
Outra diferença é a adição da cláusula INTO ao comando SELECT de modo que se possa
selecionar valores diretamente para variáveis ou parâmetros de saída, como mostrado no
exemplo a seguir:
CREATE PROCEDURE CUSTOMER_COUNT
RETURNS (
CUSTOMERCOUNT INTEGER)
AS
BEGIN
SELECT COUNT(*) FROM CUSTOMER INTO :CustomerCount;
SUSPEND;
END ^
Pode-se usar comandos SQL DDL em uma SP. Esta restrição se aplica aos comandos CREATE,
ALTER, DROP, SET, GRANT, REVOKE, COMMIT e ROLLBACK.
O exemplo anterior do comando SELECT que seleciona um ou mais valores para uma variável
funciona desde que o SELECT retorne apenas uma linha. Quando for preciso processar várias
linhas retornadas por um SELECT deve-se usar o comando FOR SELECT e DO como mostrado a
seguir:
CREATE PROCEDURE ORDER_LIST(
CUST_NO INTEGER)
RETURNS(PO_NUMBER CHAR(8))
AS
BEGIN
FOR SELECT PO_NUMBER FROM SALES
WHERE CUST_NO=:CUST_NO
INTO :PO_NUMBER
DO
SUSPEND;
END ^
Esta procedure pega um código de cliente de seu parâmetro de entrada e retorna os números
de todas as compras do cliente da tabela SALES (vendas). Observe que os números das vendas
são todos retornados através de uma única variável de saída. Veja como isso funciona: A palavra
chave FOR diz paro o Firebird abrir um cursor no conjunto de resultados (result set) do
comando SELECT. O comando SELECT tem que incluir a cláusula INTO que atribui cada campo
retornado pelo SELECT a uma variável local ou parâmetro de saída. O comando após a palavra
chave DO será executado para cada linha retornada pelo SELECT. O comando após o DO pode
ser um bloco de comandos delimitado por um BEGIN-END.
No exemplo acima, o comando SUSPEND diz para a stored procedure suspender a execução até
que uma solicitação de dados (fetch) seja recebida pelo cliente, então, a procedure lê o primeiro
PO_NUMBER para o parâmetro de saída e o retorna para o cliente. Cada vez que o cliente emite
uma requisição, o próximo PO_NUMBER é lido para o parâmetro de saída e retornado para o
cliente. Isso continuará até que todas as linhas retornadas pelo SELECT tenham sido
processadas. SUSPEND não é só usado com FOR SELECT. Ele é usado sempre que a stored
procedure retorna um valor para o cliente, evitando que a SP termine antes que o cliente tenha
recebido o resultado. A seguir um exemplo muito simples de uma SP que retorna um valor em
um parâmetro de saída:
CREATE PROCEDURE CUSTOMER_COUNT
RETURNS (
39
CUSTOMERCOUNT INTEGER)
AS
BEGIN
SELECT COUNT(*) FROM CUSTOMER INTO :CustomerCount;
SUSPEND;
END ^
O método normal de se criar um banco de dados e seus objetos no Firebird é criar um script
SQL, para ser executado em executor de script qualquer.
Para evitar que o executor de script confunda o final do comando com o final de cada comando
da procedure, deve-se usar o comando SET TERM, que muda o caracter de terminação de
comando. Veja abaixo:
SET TERM ^;
CREATE PROCEDURE Customer_Count
RETURNS (
CustomerCount Integer)
AS
BEGIN
SELECT COUNT(*) FROM CUSTOMER
INTO :CustomerCount;
SUSPEND;
END ^
SET TERM; ^
O primeiro comando SET TERM altera o caracter de término de comando para o caracter (^).
Note que este comando ainda tem que terminar com um ponto-e-vírgula já que este ainda será
o caracter de término até que o SET TERM ^ seja executado. O executor de script irá agora
ignorar os ponto-e-vírgula no final dos comandos no corpo da procedures. Um (^) é colocado
logo após o END final no comando CREATE PROCEDURE. Quando o executor encontra este
caracter ele processa todo o comando CREATE PROCEDURE. O último SET TERM volta o
terminador para o ponto-e-vírgula.
Para remover uma stored procedure use o comando DROP PROCEDURE como a seguir:
DROP PROCEDURE Nome_Procedure;
Somente o SYSDBA ou o proprietário da procedure podem apagá-la. Use o comando ALTER
PROCEDURE para alterar uma stored procedure. ALTER PROCEDURE tem exatamente a mesma
sintaxe do comando CREATE PROCEDURE.
Por padrão, o script de criação de um banco cria a estrutura de cada um das procedures e
depois altera cada uma implementando por completo:
CREATE PROCEDURE ADD_EMP_PROJ (
EMP_NO SMALLINT,
PROJ_ID CHAR(5))
AS
BEGIN
EXIT;
END ^
END ^
Depois de todas as procedures terem sido criadas o script criado pelo Firebird usa o comando
ALTER PROCEDURE para adicionar o corpo de cada uma. Veja:
ALTER PROCEDURE ADD_EMP_PROJ(
EMP_NO SMALLINT,
PROJ_ID CHAR(5))
AS
BEGIN
INSERT INTO employee_project (emp_no, proj_id) VALUES (:emp_no,
:proj_id);
WHEN SQLCODE -530 DO
EXCEPTION unknown_emp_id;
END
SUSPEND;
END ^
Desta forma o Firebird elimina qualquer dependência entre as procedures quando elas estão
sendo criadas. Já que o corpo de toda procedure esta vazio não pode haver dependência de
procedures chamando outra(s). Quando os comandos ALTER PROCEDURE são executados eles
podem ser rodados em qualquer ordem porque a declaração de qualquer procedure que
eventualmente seja chamada pela que está sendo alterada no momento, já existirá.
Stored procedures no Firebird são divididas em dois grupos de acordo com como são
chamadas. Procedures que retornam valores através de parâmetros de saída são chamadas de
”select procedures” porque elas podem ser usadas no lugar de um nome de tabela em um
comando SELECT.
Chamando “Select Procedures”:
“Select procedures” atribuem valores a parâmetros de saída e então executam um SUSPEND
para retornar estes valores. Abaixo, um exemplo simples de “select procedure”.
SELECT CUSTOMERCOUNT FROM PROCEDURE_CUSTOMER;
É possível ainda chamar procedures que necessitem de parâmetros de entrada a partir de um
console SQL ou dentro de uma aplicação, conforme o código abaixo:
SELECT TOTAL FROM PROCEDURE_CALC(20)
WHERE UF=’MG’
ORDER BY 1;
O parâmetro de entrada, CUST_NO, é passado para a procedure entre parênteses logo após o
nome da procedure no comando SELECT. Note também que este comando SELECT inclui uma
cláusula WHERE e uma cláusula ORDER BY.
No exemplo abaixo, temos a demonstração do uso de parâmetros na chamada de uma
procedure:
SELECT * FROM ORDER_LIST(:CUST_NO)
WHERE (PO_NUMBER > :PO_NUMBER)
ORDER BY PO_NUMBER DESC
O código a seguir foi retirado do evento “onclik” do botão “Execute” do formMostra (Código em
Delphi) como os valores são atribuídos aos parâmetros de entrada antes da stored procedure.
procedure TProcForm.SelectBtnClick(Sender: TObject);
begin
with ProcDm.OrderListQry do
begin
Params.ParamByName('CUST_NO').Value := CustomerNoEdit.Text;
Params.ParamByName('PO_NUMBER').Value := OrderNoEdit.Text;
Open;
end; //with
end;
41
O conteúdo deste capítulo é uma adaptação do artigo escrito por Bill Todd (Borland Developers
Conference San Diego 2000), traduzido por Alessandro Fernandes e publicado no site da
Comunidade Firebird de Língua Portuguesa (http://www.comunidade-firebird.org).
42
V.2. ATIVIDADE V
Passo 1: Crie uma procedure para cadastrar cotas no banco de dados clube.fdb.
Parâmetros de entrada: Id da categoria, validade, valor da cota, Quantidade de cotas
Parâmetro de saída: nenhum
Rotina: A procedure deverá incluir a quantidade informada de registros na tabela COTAS.
Informe abaixo o código fonte da procedure:
43
Triggers são semelhantes a stored procedures, exceto pelo modo como são chamadas. Triggers
são chamadas automaticamente quando ocorre uma alteração em um registro da tabela.
Características das triggers:
• Triggers são chamadas automaticamente quando os dados da tabela a qual ela esta
conectada são alterados.
• Triggers não tem parâmetros de entrada.
• Triggers não retornam valores.
• Triggers são criadas pelo comando CREATE TRIGGER.
END^
Após a palavra chave AS vem a declaração de qualquer variável local usando o comando
DECLARE VARIABLE igual ao que foi usado para stored procedures. Finalmente vem o corpo da
trigger delimitado pelos comandos BEGIN-END.
Recomenda-se a máxima atenção com a codificação de triggers para evitar uma execução em
cadeia que poderá ocasionar erro quando iniciar a primeira execução.
VI.2. BEFORE/AFTER
Triggers do tipo AFTER são usadas para garantir que a atualização que disparou a trigger esteja
completa com sucesso antes de executar outras ações. A trigger acima é um bom exemplo.
Insere uma linha na tabela “salary_history” sempre que o salário de um funcionário é alterado. A
linha de histórico contém o salário antigo e o percentual de alteração. Como a atualização do
registro do funcionário pode falhar por várias razões, como um valor em um campo que viola
restrições impostas, por exemplo, o histórico é importante somente no caso de uma atualização
completada com sucesso.
O Firebird não tem um tipo de campo com auto incremento. Ao invés disso tem uma
ferramenta mais flexível chamada GENERATOR. Um GENERATOR retorna um valor incrementado
toda vez que você o chama. Para criar um GENERATOR use o comando CREATE GENERATOR ou
CREATE SEQUENCE como a seguir.
CREATE GENERATOR CUSTOMER_ID;
Para excluir um GENERATOR basta usar o comando DROP GENERATOR. Para obter o próximo
valor de um GENERATOR use a função GEN_ID() por exemplo:
GEN_ID(CUSTOMER_ID, 1);
O primeiro parâmetro é o nome do GENERATOR e o segundo é o incremento. No exemplo
acima o valor retornado será o último valor mais um. O Incremento pode ser qualquer valor
inclusive zero, o que é muito útil para se obter o valor corrente de um GENERATOR sem alterar
seu valor. Você pode também alterar o valor de um GENERATOR a qualquer momento usando o
comando SET GENERATOR com a seguir:
SET GENERATOR CUSTOMER_ID TO 1000;
É importante saber que o incremento de um GENERATOR não depende da transação, ou seja,
não irá voltar ao valor anterior se for executado o comando ROLLBACK. GENERATORS são
frequentemente usados em triggers para fornecer um valor para uma chave primária como no
exemplo a seguir:
CREATE TRIGGER SET_EMP_NO FOR EMPLOYEE
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
new.emp_no=gen_id(emp_no_gen, 1);
END ^
É possível usar a função GEN_ID em uma stored procedure que retorna o valor do GENERATOR
em um parâmetro de saída para a aplicação cliente. O cliente pode então atribuir o valor a sua
chave primária e apresenta-la ao usuário quando este cria um novo registro antes mesmo que
este tenha sido gravado com um POST. Neste caso recomenda-se criar uma trigger como a
mostrada acima para o caso de um cliente inserir um registro e não fornecer um valor para a
chave primária. Basta alterar o código conforme a seguir:
IF new.emp_no IS NULL THEN new.emp_no = gen_id(emp_no_gen, 1);
Agora a trigger só irá fornecer um valor para a chave primária no caso do campo ser nulo.
Basta usar o comando ALTER TRIGGER para alterar tanto o cabeçalho quanto o corpo da trigger.
O uso mais comum da alteração do cabeçalho é ativar e desativar uma trigger. Outro uso é
trocar o POSITION da trigger. O comando a seguir irá inativar a trigger.
ALTER TRIGGER SET_EMP_NO INACTIVE;
Para alterar o corpo da trigger preserve seu nome, as outras informações do cabeçalho e
informe o novo corpo como mostrado a seguir:
ALTER TRIGGER SET_EMP_NO
AS
BEGIN
IF new.emp_no IS NULL THEN new.emp_no = gen_id(emp_no_gen, 1);
END ^
Para apagar uma trigger use o comando DROP TRIGGER. Por exemplo:
DROP TRIGGER SET_EMP_NO;
46
O conteúdo deste capítulo é uma adaptação do artigo escrito por Bill Todd (Borland Developers
Conference San Diego 2000), traduzido por Alessandro Fernandes e publicado no site da
Comunidade Firebird de Língua Portuguesa (http://www.comunidade-firebird.org).
47
VI.7. ATIVIDADE VI
Segundo (CANTU, 2006), View é uma representação personalizada das informações de uma ou
mais tabelas do banco de dados. Os dados retornados por uma View são recuperados no
momento de sua execução. Essas visões podem ser acessadas através do comando SELECT
convencional, bastando para isto indicar o nome da view no lugar do nome da tabela.
De acordo com (DATE, 2003) uma view serve para:
• Fornecem um recurso de abreviação ou de “macro”;
• Permitem que os mesmos dados sejamvistos por usuários diferentes de modos diferentes
de modos diferentes ao mesmo tempo;
• Fornecem segurança automática para dados ocultos;
• Podem fornecer independência de dados lógicos;
Quando uma visão é definida, o sistema de banco de dados armazena sua definição ao invés do
resultado da expressão SQL que a definiu. Sempre que a relação visão é usada, ela é sobreposta
pela expressão da consulta armazenada, de maneira que, sempre que a consulta for solicitada, a
relação visão será recomputada.
Alguns sistemas de banco de dados permitem que as relações de visões sejam materializadas,
garantindo que se ocorrerem modificações nas relações reais usadas na definição da visão,
também a visão será modificada. Contudo, esta abordagem pode incorrer em custos de
armazenamento e atualizações de sistema.
Uma view é atualizável quando reúne as características necessárias para permitir que operações
de manipulação de dados (inserção, remoção ou atualização) nas tabelas utilizadas por ela,
possam ser feitas diretamente na própria view.
Se uma view possuir algumas das características listadas abaixo, ela não será “naturalmente
atualizável”:
• Utilizar UNIONs;
• Trazer dados de mais de uma tabela (Joins)
• Trazer dados de outra view que não seja atualizável;
• Possuir campos definidos por subqueries, funções de agregação (count, sum, etc) ou
outras expressões;
• Deixar de recuperar algum campo definido como NOT NULL, na tabela utilizada;
• Utilizar GROUP BY;
• Utilizar as cláusulas distinct, first, skitp ou rows;
Na maioria das vezes, views que não são “naturalmente atualizáveis”, devido a alguma das
razões expostas acima, poderão se tornar atualizáveis através da criação de triggers que serão
responsáveis pela manipulação dos dados nas tabelas referenciadas pela view.
Uma view é naturalmente atualizável se:
• Recuperar informações de uma única tabela ou view atualizável;
• Listar todos os campos not null da tabela ou view referenciada;
• Não utilizar funções de agregação, subqueries,UDFs, etc.
Controle de acesso às views
O usuário que está criando a view deve ter direito de acesso (select) nas tabelas acessadas perla
view.
Todos os usuários que acessarem a view deverão ter direito de acesso à view concedidos. E
ainda é necessário que o dono da view, ou usuário que está acessando, ou a própria view tenha
direito de acesso às tabelas acessadas por ela.
No caso de view naturalmente atualizável, é necessário que a mesma tenha direitos de select,
update, insert e delete na tabela utilizada. Caso a view seja atualizada através de trigger, cada
trigger deverá ter seu direito de acesso garantido nas tabelas que serão manipuladas, para as
respectivas operações.
Outro exemplo de view:
CREATE VIEW V_ASSOCIADOS(
SOC_ID, SOC_NOME, SOC_CPF,
SOC_TITULAR, SOC_NASCIMENTO, SOC_ENDER_RES,
SOC_ENDER_COB, SOC_ADMISSAO, SOC_VENCIMENTO,
SOC_CELULAR, SOC_COTA, SOC_CATEG,
SOC_VALMENSAL, SOC_EMAIL,
SOC_STATUS, ENDRES_TIPOLOG,
ENDRES_NOMELOG, ENDRES_NUMERO,
ENDRES_COMPL, ENDRES_BAIRRO,
ENDRES_MUNIC, ENDRES_CEP,
ENDRES_FONEFIXO, ENDRES_INCLUSAO,
ENDRES_ALTERACAO, ENDCOB_TIPOLOG,
ENDCOB_NOMELOG, ENDCOB_NUMERO,
ENDCOB_COMPL, ENDCOB_BAIRRO,
ENDCOB_MUNIC, ENDCOB_CEP,
ENDCOB_FONEFIXO, ENDCOB_INCLUSAO,
ENDCOB_ALTERACAO, CATEGORIA)
AS
SELECT S.SOC_ID, S.SOC_NOME, S.SOC_CPF, S.SOC_TITULAR, S.SOC_NASCIMENTO,
50
Passo 1: Crie uma view para exibir apenas os sócios devedores. Deverão ser definidos os
seguintes campos: CPF, Nome do sócio e valor total dos débitos:
51
Figura 5 - Transação
Principais propriedades de uma transação (ACID):
• Atomicidade: Ou todas as ações da transação acontecem, ou nenhuma delas acontece.
• Consistência: Se a transação é consistente e o BD começa consistente, ele termina
consistente.
• Isolamento: A execução de uma transação é isolada da execução de outras transações.
• Durabilidade: Se uma transação é concluída com sucesso (através de uma operação
commit bem sucedida), então seus efeitos são persistentes (duráveis).
A sintaxe básica de transação é:
SET TRANSACTION [NAME transaction]
[READ WRITE | READ ONLY]
[WAIT | NO WAIT]
[[ISOLATION LEVEL] {SNAPSHOT [TABLE STABILITY]
| READ COMMITTED [[NO] RECORD_VERSION]}]
[RESERVING <reserving_clause>
| USING dbhandle [, dbhandle ...]];
<reserving_clause> = table [, table ...]
[FOR [SHARED | PROTECTED] {READ | WRITE}] [, <reserving_clause>]
52
É o tipo, ou modo de acesso que a transação terá no banco de dados. Os tipos de acesso
podeM ser:
(Leitura & Gravação): é o modo padrão. Ele provê ao usuário, que iniciou a transação, o poder
de ler informações e alterar o conteúdo do banco de dados;
(Somente leitura): permite ao usuário apenas ler as informações do banco de dados não
permitindo a ele executar comandos que possam alterar qualquer conteúdo.
Observe que o modo RW pode executar, dentro do seu contexto, comandos como
INSERT/UPDATE/DELETE e o modo RO permitem somente os comandos SELECT/REFERENCE.
Especificam como o servidor procederá quando ocorrer algum conflito de leitura ou gravação
dos dados.
VIII.2.1. WAIT
O modo padrão é WAIT (esperar), neste modo o usuário que encontrou o conflito fica
aguardando até que a transação anterior que ainda não foi confirmada seja encerrada. O
controle não retorna para o cliente até que a operação possa continuar.
VIII.2.2. NO-WAIT
No modo NO-WAIT (sem esperar), o usuário que gerou o conflito com outra transação não
confirmada receberá uma mensagem de erro imediatamente.
Os conflitos podem aparecer não somente em operações de gravação, mas também em
operações de leitura.
Chamado “Dirty Read” (leitura suja) permite a uma transação ler todas as mudanças feitas por
outra transação em qualquer registro, mesmo que estas mudanças não tenham sido
confirmadas. Este nível não é recomendado para bancos relacionais por que ele permite ler
inconsistências e informações parciais. Os valores que uma transação UPDATE/INSERT/DELETE
no banco de dados, depois de confirmados, devem ser vistos pelas outras transações com um
novo estado consistente do banco de dados, e o modo de isolamento “dirty read” vai contra
esta idéia básica. Este nível não é suportado pela maioria dos SGDBs. DB2 e Informix suportam.
Na maioria dos servidores relacionais, este é o nível típico de qualquer mecanismo. Ele permite
a transação ler somente mudanças confirmadas feitas por outras transações.
53
Este nível de isolamento ajuda a garantir que as transações verão apenas estados consistentes
do banco (é claro que isto assume que todos os clientes irão fazer um conjunto de mudanças
inter-relacionadas dentro de uma transação englobada). Mesmo se uma transação confirmar
depois de uma outra transação, usando “read committed” ter iniciado, estas mudanças poderão
ser lidas. Existem dois sub-modos que se aplicam somente a este nível:
Record version - a última versão confirmada do registro é lida imediatamente. Esta é o padrão.
No Record version - se estiver ali uma versão não confirmada de um registro gerado por outra
transação, a transação atual fará o seguinte: se o Tipo de Bloqueio for WAIT, ela irá esperar até o
registro ser confirmado (commit) ou descartado (rollback), ou se o Tipo de Bloqueio for NO-
WAIT um erro será gerado imediatamente. De qualquer forma, a transação sempre tentará ler a
versão mais recente de um registro. Isto se aplica a mudanças feitas por outras transações, por
que uma transação sempre pode ler suas mudanças não confirmadas. Este sub-modo causa a
exibição de mensagens de “deadlock”, e por isto deve ser usado com muito cuidado.
VIII.3.3. Snapshot
Chamado de “Repeatable Read” (leitura repetitiva) permite que uma transação possa obter uma
imagem completa do banco de dados quando ela for iniciada. Esta transação não consegue ver
qualquer mudança feita por outras transações concorrentes. Este nível é ideal para relatórios,
porque na mesma transação, um registro pode ser lido muitas vezes, e seu valor deve ser o
mesmo até que a sua própria transação mude algum valor. Esta transação pode ver mudanças
feitas por ela mesma. Este nível de isolamento não é recomendado para usuários interativos, por
que eles precisam de dados atuais, e não de dados congelados. Pode ser usado para operações
obrigatórias e, portanto devem ser confirmadas ou descartadas; por que ela previne “garbage
collection” (lixos): todas as versões até o momento que a transação foi iniciada se manterão
para manter uma visão estável do banco de dados. Um servidor relacional “normal” paga um
preço caro em performance ou recursos para suportar este modo.
Conhecido também pelo nome de “Forced Repeatable Read” (leitura repetitiva forçada), este
nível é específico do Firebird/Interbase e não existe em outro servidor relacional. Ele pode ser
chamado de escrita de estabilidade “Snapshot”, porque ela tem as mesmas propriedades do
nível anterior, mas também quando for feita a leitura da tabela esta será bloqueada para escrita,
para as outras transações. Então, a transação com este nível tem o controle sobre a tabela e
todas as outras transações poderão somente ler a partir desta tabela. Este nível não é
recomendado para propósitos gerais; ele só deve ser utilizado quando realmente for necessário
e em curtos períodos de tempo deve ser confirmada ou descartada, porque cada uma das
outras transações que estiverem tentando gravar na mesma tabela receberá uma mensagem de
erro ou será colocada em espera até que a transação seja concluída. Este nível pode gerar
muitos conflitos ou causar um “deadlock” geral no banco de dados.
Também pode ser chamado de “table reservation” (reserva de tabela) na documentação oficial.
Como SET TRANSACTION está disponível em SQL, DSQL e ISQL, ele pode ser embutido em
aplicações SQL. Ele permite um fino acabamento através dos recursos requisitados (neste caso,
tabelas) quando uma transação inicia no lugar de ficar aguardando, a transação tenta suas
operações na tabela. Esta técnica reduz a possibilidade de deadlocks. A cláusula RESERVING
54
(reservando), é seguida de uma lista de tabelas separadas por vírgula e depois a palavra
reservada FOR que tem as seguintes opções de compartilhamento:
SHARED: as tabelas podem ser compartilhadas com outras transações concorrentes para leitura.
PROTECTED: as tabelas não podem ser compartilhadas com outras transações para leitura ou
gravação.
Opções de modo de acesso:
READ: a transação irá querer antecipar somente usos do tipo RO, de acordo com uma ou outra
opção de compartilhamento mostrada anteriormente.
WRITE: a transação irá querer antecipar uso de WRITE nas tabelas, de acordo com uma ou outra
opção de compartilhamento mostrada anteriormente. Há quatro possibilidades de combinação.
Depois da vírgula pode-se colocar uma lista de tabelas separadas por vírgula e seguida da
palavra reservada FOR e seu modo de pré-alocação desejado. Tente uma dessas quatro
combinações:
Shared, write: permite a qualquer transação com modo de acesso WRITE e nível de isolamento
“concurrency” ou “read committed”, atualizar enquanto outras transações com outros níveis de
isolamento e acesso READ podem ler dados.
Shared, read: permite a qualquer transação ler dados, e qualquer transação com acesso WRITE
a atualizar. Este é modo de reserva mais liberal.
Protected, write: previne que outras transações atualizem. Outras transações com níveis de
isolamento “concurrency” ou “read committed” podem ler dados, mas somente esta transação
pode atualizar.
Protected, read: previne que todas as transações atualizem, mas permite que todas as
transações leiam os dados.
Outro exemplo:
Passo 1: Faça duas conexões ao banco de dados clube.fdb e realize testes de transação.
Execute um update na tabela de sócios nas duas conexões.
Execute COMMIT WORK na segunda e tente fazer o mesmo na primeira.
56
Este capítulo será apresentado a partir do documento de divulgação do trabalho em grupo que
valerá como terceira nota da disciplina.
57
Autonomia local – apesar de existirem diversos servidores no sistema, para o cliente existe
somente um servidor de dados, sendo transparente para o mesmo, a distribuição tanto dos
dados como do processamento.
Inexistência de um servidor central – em um sistema distribuído não há uma hierarquia de
servidores, mas todos podem trabalhar independentemente. Com a queda de um servidor, o
sistema continua executando, mas com uma redução de recursos proporcional à representação
do potencial computacional do servidor que caiu em relação ao sistema.
Operação contínua – uma importante característica de um sistema de dados distribuído é a sua
alta tolerância a falhas tanto de hardware, software, como de rede. Em um sistema monolítico,
havendo falha em qualquer dos quesitos mencionados anteriormente, ocorre a
indisponibilidade do mesmo. Em um sistema distribuído, as chances de indisponibilidade são
inversamente proporcionais à quantidade de servidores. Havendo falha em um servidor, o
sistema poderá continuar processando de forma reduzida ao invés de sair do ar. Há uma queda
de desempenho, e até indisponibilidade de alguns dados, mas não a indisponibilidade do
serviço.
Independência de localização – em um sistema distribuído, o cliente solicitará qualquer dado
existente no sistema sem a preocupação em acessar o servidor onde se encontra armazenada
cada informação. Para o cliente, todas as informações estarão no servidor que ele acessa.
Independência de fragmentação – um sistema de bancos de dados distribuído deverá acatar a
possibilidade fragmentar os dados de forma a manter em um servidor as informações que seus
clientes solicitam mais, distribuindo assim os dados e o processamento das informações. Estes
dados são unificados por meio de junções para fragmentações verticais (colunas) e de uniões
para fragmentações horizontais (tuplas). Para o cliente esta fragmentação não é visível.
Processamento de consultas distribuído – o sistema distribuído é capaz de envolver diversos
servidores na otimização e execução de consultas a dados considerando a localização dos
mesmos, sendo transparente para o usuário.
Gerenciamento de transações distribuído – um sistema distribuído será capaz de conferir
atomicidade a uma transação, mesmo que ela envolva servidores diferentes.
Independência de hardware – um sistema de dados distribuído deve operar em cima de uma
abstração de software capaz de operar em diferentes arquiteturas – daí o suporte a diversos
tipos de hardwares.
58
O banco de dados usado como exemplo refere-se a fornecedores, com número, nome e cidade-
sede; peças, com código e nome; e fornecimentos relacionando um fornecedor a cada peça que
fornece e indicando a quantidade fornecida. Assumindo que o banco é descrito no modelo
relacional, o esquema conceitual seria:
Esquema Conceitual Global
FORNECEDORES [ NUMERO,NOME,SEDE ]
PECAS [ CODIGO,NOME,COR,PESO ]
FORNECIMENTO [ NUMERO,CODIGO,QUANTIDADE ]
Poderíamos definir dois esquemas externos globais da seguinte forma:
Esquema Externo Global A:
Esquema de relação:
FORN_PECA [ NUMERO,CODIGO,NOME ]
Definição:
FORN_PECA = (FORNECIMENTO * PECAS) [ NUMERO,CODIGO,NOME ]
Esquema Externo Global B:
Esquema de relação:
FORN_PECA [ NUMERO,CODIGO ]
Definição:
FORN_PECA = FORNECIMENTO [ NUMERO,CODIGO ]
A álgebra relacional será usada para indicar mapeamentos neste exemplo; a operação de junção
natural será indicada pelo símbolo '*' e as operações de projeção e seleção serão denotadas da
forma usual, ou seja, R[X] indicará a projeção de R na lista de atributos X e R[B], onde B é uma
qualificação, indicará uma seleção das tuplas de R que satisfazem B.
Assumindo que o sistema é homogêneo e distribuído em apenas dois nós, os esquemas
conceituais locais e a distribuição do esquema conceitual global seriam então descritos da
forma abaixo (o primeiro nó conterá todos os fornecedores com sede em Varginha, todos os
fornecimentos em que estão envolvidos e o nome e código das peças; o segundo nó conterá o
resto dos fornecedores e seus fornecimentos, além do código, cor e peso das peças.
Esquemas Conceituais Locais:
Primeiro Nó:
FORNECEDORES1 [ NUMERO,NOME,SEDE ]
PECAS1 [ CODIGO,NOME ]
FORNECIMENTO1 [ NUMERO,CODIGO,QUANTIDADE ]
Segundo Nó:
FORNECEDORES2 [ NUMERO,NOME,SEDE ]
PECAS2 [ CODIGO,COR,PESO ]
FORNECIMENTO2 [ NUMERO,CODIGO,QUANTIDADE ]
Mapeamentos Definindo o Critério de Distribuição:
Primeiro Nó:
FORNECEDORES1 = FORNECEDORES [ SEDE='PASSA TRES' ]
PECAS1 = PECAS [ CODIGO,NOME ]
FORNECIMENTO1 = FORNECIMENTO * (FORNECEDORES1 [ NUMERO]
Segundo Nó:
FORNECEDORES2 = FORNECEDORES [ SEDE ≠ 'PASSA TRES' ]
FORNECIMENTO2 = FORNECIMENTO * (FORNECEDORES2 [ NUMERO]
PECAS2 = PECAS [ CODIGO,COR,PESO ]
60
Como os esquemas internos locais dependem do SGBD local em questão, não faz sentido
apresentá-los aqui. Esquemas externos locais também são omitidos.
Em primeiro lugar, o projeto do esquema conceitual global e o dos esquemas externos globais é
inteiramente semelhante ao caso centralizado, já que o banco de dados distribuído deverá se
comportar como centralizado perante os usuários globais. Além disto, o projeto dos esquemas
internos locais é também idêntico ao de bancos centralizados, exceto que a carga imposta por
acessos remotos aos dados locais também deve ser levada em consideração. Portanto, o
problema básico de projeto de bancos de dados distribuídos reside no projeto dos esquemas
conceituais locais, pois estes refletem a estratégia de distribuição do banco.
As estratégias de distribuição são classificadas em particionamento e replicação. Seja D uma
estrutura (lógica) de dados do esquema conceitual global. Dizemos que D é particionada
verticalmente (ou estruturalmente) quando D é mapeada em duas ou mais estruturas (lógicas)
de dados que não são idênticas a D e que pertencem a diferentes esquemas conceituais locais.
Dizemos que D é particionada horizontalmente (ou particionada por ocorrência) quando D é
mapeada em estruturas idênticas a D e pertencentes a dois ou mais esquemas conceituais locais
de tal forma que o mapeamento define um particionamento (no sentido matemático) do
conjunto de dados associado a D.
No exemplo anterior, FORNECEDORES foi particionada horizontalmente em FORNECEDORES1 e
FORNECEDORES2, o mesmo acontecendo com FORNECIMENTO. Já PECAS foi particionada
verticalmente em PECAS1 e PECAS2.
Dizemos que D é replicada quando D é mapeada em duas ou mais estruturas (lógicas) de dados
idênticas a D e pertencentes a diferentes esquemas conceituais locais de tal forma que o
mapeamento de D em cada uma destas estruturas é sempre a identidade. Ou seja, existirão
cópias idênticas do conjunto de dados associado a D armazenadas em dois ou mais nós. A
replicação é total quando cada banco de dados local contém uma cópia completa do banco.
Caso contrário, a replicação é parcial.
A escolha da estratégia de distribuição do banco exige cuidados especiais, pois, se vier a gerar
um tráfego de dados exagerado entre os vários nós, o custo de comunicação tornará o projeto
anti-econômico.
Inicialmente, deve-se verificar se a solução distribuída é de fato uma opção viável. Isto significa,
essencialmente, detetar se o banco é fortemente integrado, ou se pode ser dividido em partes
mais ou menos independentes; se este for o caso, deve-se então determinar qual a vantagem
de descentralizar o banco. Um estudo do perfil da população de transações existentes no
sistema centralizado em uso (se este for o caso) deverá ser feito, tentando determinar se é
possível dividir o sistema - banco de dados e transações - em subsistemas mais ou menos
independentes. Se este for o caso, o custo de transmissão de dados deverá ser reduzido,
descentralizando-se o banco e suas funções. Acessos que cortem fronteiras geográficas ainda
serão suportados, desde que não sejam muito freqüentes. Uma vez identificado que a solução
distribuída é viável, deve-se escolher a técnica de distribuição, levando-se em conta os
seguintes fatores:
Particionamento:
61
Finalmente, uma vez estabelecidas regras para administração do banco, a equipe deverá auditar
periodicamente o sistema para assegurar a aderência a tais regras. A carga, tempo de resposta e
utilização do sistema deverá ser constantemente monitorada, prevendo-se reestruturação do
banco ou mudanças nas regras de administração para corrigir desequilíbrios.
Os problemas a serem enfrentados pela equipe de administração para atingir os seus objetivos
podem ser compreendidos considerando-se três cenários básicos para um banco de dados
distribuído.
Se o BDD resultou da interligação de sistemas existentes então certamente aparecerão
problemas devidos a: heterogeneidade do sistema global, introdução de padrões globais sem
que seja comprometida a autonomia local, critérios de alocação de custos tendo em vista
acessos locais e remotos, além do balanceamento do tempo de resposta de acessos locais e
remotos.
Se o cenário admite a criação de novos bancos locais de forma semi-autônoma, aparecerão
problemas relativos a: definição de regras e responsabilidades locais, descrição da semântica
dos dados definidos localmente, grau de cooperação entre os núcleos locais, principalmente no
que se refere à alocação de recursos para processamento de acessos remotos.
Finalmente, em um cenário onde o BDD foi criado pela distribuição em nós homogêneos de um
sistema centralizado, haverá o problema fundamental de definir uma estratégia de distribuição
que otimize o tempo de resposta global, sem penalizar demasiadamente grupos de usuários.
Resumo:
Um Sistema de Banco de Dados Distribuído oferece maior disponibilidade, confiabilidade,
segurança e maior desempenho. Porém sua implementação é mais cara e sua manutenção é
mais dispendiosa. Um banco de dados distribuído é uma solução ideal para sistemas de alta
disponibilidade como bancos e grandes sites de compras da Internet. Cabe ao engenheiro do
sistema escolher a opção de armazenamento e acesso a dados mais viável para sua aplicação.
64
X.5. ATIVIDADE X
O objeto é formado como se fosse uma tripla (i, c, v), onde o i é o OID do objeto, o c é um
construtor, ou seja, que tipo de valor ele vai receber exmplo: atom, tuple, set, list, bag, array e v
é o valor corrente. Então o objeto passa a suportar aquilo que foi definido para ele. Se ele vai
receber um valor atômico ele só aceitará valores atômicos.
Os construtores de tipos sets, bags, lists e arrays são caracterizados como tipos de coleções e a
diferença entre eles é a seguinte: sets e bags, o primeiro só aceita valores distintos enquanto o
66
segundo aceita valores duplicados. Lists e arrays, o primeiro só aceita números arbitrários,
enquanto o segundo, o tamanho deve ser pré-estabelecido.
Umas das características dos sistemas OO é ocultar informação e tipos abstratos de dados,
sendo que é muito complicado aplicar esse modelo na prática. Por exemplo, nos sistemas atuais
para uma consulta em uma determinada tabela é necessário saber todos os atributos da tabela,
para formar a consulta. Em um sistema OO, que preza pelo encapsulamento nem toda tabela
pode enxergar a outra, o que dificultaria muito as consultas.
A idéia do encapsulamento em um BD OO, já que não dá para ser aplicado a rigor, é pelo
menos tratar o comportamento do objeto com funções pré-definidas. Por exemplo, insert,
delete, update etc. Ou seja, a estrutura interna do objeto é escondida, e os usuários externos só
conhecem a interface do tipo de objeto como os argumentos (parâmetros), de cada operação.
Então a implementação é oculta para usuários externos que está incluído a definição da
estrutura interna, de dados do objeto e a implementação das operações que acessam essas
estruturas. Enfim o BD OO propõe o seguinte, dividir estrutura do objeto em partes visíveis e
ocultas então para operações que exigem atualização da base de dados torna se oculta e para
operações que exige consultas, torna-se visível. (ELMASRI, 2005).
Em grande parte, os bancos de dados OO tem suas restrições com relação às extensões, isto é,
as extensões possuem o mesmo tipo ou classe. Na Linguagem OO nem sempre é assim.
SMALLTALK, por exemplo, permite ter uma coleção de objetos de diferentes tipos.
É comum em aplicações de banco de dados que cada tipo ou subtipo de dado possua uma
extensão associada, que mantenha a coleção de todos os objetos persistentes daquele tipo ou
subtipo. Nesse caso, a restrição é de que todo objeto numa extensão que corresponda a um
subtipo também deva ser um membro de extensão que corresponda a seu supertipo. Alguns
sistemas de banco de dados OO possuem um tipo de sistema predefinido (chamado de classe
raiz (root) ou classe OBJETO, cuja extensão contém todos os objetos do sistema. A classificação
então segue, designando objetos para supertipos adicionais que são significativos para a
aplicação, criando uma hierarquia de tipo ou hierarquia de classe para o sistema).
Grande parte do modelo OO separa claramente o que é objeto persistente, e objeto transiente.
Por exemplo, quando é realizada uma consulta, é carregada uma lista de objetos numa classe
transiente (temporária), o sistema pode manipular os dados nessa classe e assim que forem
feitas as manipulações necessárias elas deixam de existirem.
Uma das grandes vantagens de um SGBDOO é que ele permite salvar objetos grandes e depois
obter a recuperação facilmente desses grandes objetos como texto longos, imagens etc. Eles
são considerados não estruturados porque o SGBD não conhece a sua estrutura. A aplicação
pode utilizar várias funções para manipular esses objetos. E o mais importante é que o SGBD
não conhece essas funções, mas através de técnicas oferecidas por ele é capaz de reconhecer
esses
objetos e buscá-los no banco de dados. Caso o objeto seja muito grande ele pode utilizar
técnicas como buffering e caching.
É importante frisar que SGBDOO não é capaz de processar diretamente condições de seleções e
outras operações desses objetos. É necessário que esses dados sejam passados para o BD para
que ele possa saber tratar os objetos corretamente. Por exemplo, considere objetos que são
imagens bitmap bidimensional. Suponha que a aplicação precise selecionar a partir de uma
coleção de tais objetos somente aqueles que incluem certo padrão. Nesse caso, o usuário deve
fornecer o programa de reconhecimento do padrão, como um método em objetos do tipo
bitmap. O SGBDOO recupera, então, um objeto do banco de dados e aplica nele o método para
o reconhecimento do padrão para determinar se o objeto adere ao padrão desejado.
67
Objetos complexos estruturados são os objetos que contém vários tipos de objetos dentro
deles. Por exemplo, um objeto é composto de um list, de tupla, de um set, isto é, o SGBDOO
conhece todas essas estruturas, porém o objeto se torna complexo por composto de tipos de
objetos diferentes.
Existem vários bancos de dados orientados a objeto, discutir cada um deles é essencial para a
tomada de decisão. É importante saber qual modelo é mais apropriado para o uso da sua
aplicação. A seguir estão alguns exemplos:
CACHÉ: trabalha com as seguintes linguagens: Java, .Net, C++, XML e outras. É um banco de
dados comercial.
VERSANT: trabalha com as seguintes linguagens: Java e C++. É bastante utilizado nos sistemas
telecomunicações, redes de transporte, áreas médicas e financeiras. É um banco de dados
comercial.
DB4Objects: Trabalha com as seguintes linguagens: Java e .Net. Sua linguagem de Consulta é a
Object Query Language (OQL) e é um banco de dados distribuído em duas licenças, a GPL
(licença pública Geral) e uma licença comercial.
O2: Trabalha com as seguintes linguagens: C, C++ e o ambiente O2. Sualinguagem de Consulta:
O2Query, OQL. Seu gerenciador do Banco de Dados é oO2Engine, e é um banco de dados
comercial.
GEMSTONE: trabalha com as seguintes linguagens: Java, C++, C#, XML e outras. Sua linguagem
de Consulta é o DML. É um banco de dados comercial.
JASMINE: Possui alta conectividade com Web, suporte à linguagem Java. Pode-seainda
desenvolver aplicações em Visual Basic usando Active/X, em HTML(HyperText Markup
Language) usando as ferramentas de conectividade para Web disponíveis no Jasmine, em C e
C++ usando APIs e em Java usando interfaces demiddleware embutidas no Jasmine. É um
banco de dados comercial.
MATISSE: Trabalha com as seguintes linguagens: Java, C#, C++, VB, Delphi, Perl,PHP, Eiffel,
SmallTalk. É um banco de dados comercial.
Objectivity/DB: trabalha com as seguintes linguagens: C#; C++; Java; Python,Smalltalk; SQL++
(SQL com objeto - extensões orientadas) e XML (para aimportação e a exportação somente). É
um banco de dados comercial.
Ozone: trabalha com as seguintes linguagens: Java e XML. É um banco de dados opensource.
A ODL foi feita para dar suporte aos construtores semânticos do modelo de objetos ODMG e é
independente de qualquer linguagem de programação em particular. O objetivo da ODL é criar
especificações de objetos, isto é, classes e interfaces. A ODL não é considerada uma linguagem
de programação completa. Ela permite que o usuário especifique um banco de dados
independente da linguagem de programação, e utilizando o binding específico com a
linguagem para especificar como os componentes ODL podem ser mapeados para
componentes em linguagens de programação específica, como C++, SmallTalk e Java.
68
É a linguagem de consulta declarativa definida pela ODMG (1995). Prevê suporte ao tratamento
de objetos complexos, invocação de métodos, herança e polimorfismo. É projetada para
trabalhar acoplada com as linguagens de programação com as quais o modelo ODMG define
um biding, como C++, SMALLTALK e JAVA. Isso faz com que qualquer consulta OQL embutida
em uma dessas linguagens de programação pode retornar objetos compatíveis com os
sistemas de tipos dessa linguagem. Fornece suporte para lidar com set, structure, list e array,
tratando estas construções com a mesma eficiência. Permite expressões aninhadas. Pode
chamar
métodos dos tipos envolvidos na consulta. Não fornece operadores para atualização, mas pode
chamar operações definidas nos objetos para realizar esta tarefa, não violando assim a
semântica do modelo de objetos, o qual, por definição, é gerenciado pelos métodos
especificados no objeto. É possível definir um nome para uma determinada consulta, que é
armazenada no BD. Para uso posterior, a consulta é referenciada através do nome definido.
Apresenta construtores de objetos, structure, set, list, bag e array. Uma consulta em OQL parte
dos pontos de entrada do banco de dados e constrói como resposta, um objeto que é
tipicamente uma coleção. Suporta as cláusulas SELECT, FROM, WHERE, GROUP BY, HAVING e
ORDER BY.
A sintaxe básica da OQL é uma estrutura select ... from ... where, igual a da SQL. A seguir será
mostrado uma consulta, o nome de todos os departamentos na faculdade 'Engenharia‟:
SELECT d.dnome From d in departamentos WHERE d.faculdade ='Engenharia';
Na maioria das vezes, é necessário um ponto de entrada para o banco de dados para cada
consulta, que pode ser qualquer objeto persistente nomeado. Em muitas consultas, ponto de
entrada é o nome da extensão de uma classe, ou seja, uma extensão é considerada como sendo
o nome de um objeto persistente cujo tipo é uma coleção. Onde na maioria das vezes é um
conjunto, exemplos: set<Pessoa>, set<Professor>, set <Disciplinas> e assim por diante.
A utilização de um nome de extensão, por exemplo, departamentos em OQL, como um ponto
de entrada refere-se a uma coleção persistente de objetos. Toda vez que uma coleção for
referenciada em uma consulta OQL, devemos definir uma variável de interação (é parecido com
as variáveis de tupla que percorrem as tuplas nas buscas da SQL), d em OQL que percorre cada
objeto na coleção.
A consulta exemplificada irá selecionar certos objetos de acordo com a cláusula where
d.faculdade = 'Engenharia' e serão selecionados para o resultado da consulta. Sendo assim o
resultado da consulta é do tipo Bag<string> porque o tipo de cada valor dnome é recuperado
no resultado da consulta (embora o resultado seja um set porque dnome é um atributo chave).
É importante ressaltar que em geral, uma consulta seria do tipo bag para select ... from ... e do
tipo set para select distinct.
Existem três tipos de opções para especificar variáveis de interação: d in departamentos,
departamentos d, departamentos as d.
É importante ressaltar que qualquer objeto persistente nomeado que se refira a um objeto
atômico (simples) ou a um objeto coleção pode ser utilizado como um ponto de entrada para o
banco de dados.
69
Uma consulta não precisa seguir necessariamente a estrutura select ... from ... where ... . Por
exemplo, qualquer nome persistente por si mesmo é uma consulta, e neste cado o resultado é
uma referência a esse objeto persistente.
Por exemplo,
Q1: departamentos;
Neste caso, retorna uma referência à coleção de todos os objetos persistentes em
departamentos, cujo tipo seja set <departamento>.
Caso um nome persistente departamentocc estivesse atribuído a um departamento específico,
tipo 'ciencia da computação'. Q1a: departamento; O resultado seria “ciência da computação‟.
Uma vez que o ponto de entrada é especificado, o resultado, o conceito de expressão de
caminho (path expression) pode ser utilizado para indicar o caminho de atributos e objetos
relacionados. Normalmente, uma expressão de caminho inicia-se pelo nome de um objeto
persistente ou pela variável de interação que percorre os objetos individuais de uma coleção.
Esse nome será acoplado por zero ou mais nomes de relacionamentos ou nomes de atributos
conectados utilizando-se a notação de ponto.
Fórmula 6: q10: Retorna os nomes de todos os alunos que completaram o curso chamado
'sistema de banco de dados I'. Fonte: ELMASRI, 2005.
A OQL Q10 mostra um modo mais simples de se especificar a clausula select de consultas que
retornam uma coleção de estruturas.
Consultas que retornam valores booleanos, true ou false. Assume-se que exista um objeto
jeremy do tipo Aluno. Então a consulta Q11, responde à seguinte pergunta: “jeremy se
especializa em ciencias da computaçao”. E a Q12, responde à pergunta “Todos os alunos de
ciência da computação são orientados por professores do departamento de ciência da
computação”. Tanto Q11 quanto Q12 retornam true ou false, que são interpretados como
resposta sim ou não para perguntas anteriores.
Q11: jeremy in especializa_em (ciencia da
computação);
Q12: for all g in (select s from s in grad_aluno
where s.especializa_em.dnome = 'ciencia da
computação') : g.orientado_por in
departamentocc.trabalha_em;
Fórmula 7: Q11: Responde à seguinte pergunta: “jeremy se especializa em ciencias da
computação?” Q12: responde à pergunta “Todos os alunos de ciência da computação são
orientados por professores do departamento de ciência da computação ?” Fonte: ELMASRI,
2005.
Pode ser observado na consulta Q12 a herança de atributos, relacionamentos e operações é
aplicada em consultas. Seja s um interator que percorre grad_aluno, pode se escrever
s.especializa_em porque o relacionamento especializa_em é herdado por Grad_Aluno de Aluno
via Extends. Para finalizar, será mostrado o quantificador exists, representado na consulta Q13,
respondendo a seguinte pergunta: “Algum aluno de ciencia da computação possui mdc (média
das disciplinas cursadas) igual a 4.0 ?”. Também é possível notar a operação mdc herdada da
classe Grad_Aluno de Aluno via Extends.
Q13 : exists g in (select s from s in grad_aluno
where s.especializa_em.dnome = 'ciencia da
computacao'; : g.mdc = 4;
Fórmula 8: Q13: respondendo a seguinte pergunta: “Algum aluno de ciencia da computação
possui mdc (média das disciplinas cursadas) igual a 4.0?” Fonte: ELMASRI, 2005.
Podem existir casos de recuperar o i-ésimo, do primeiro e do último elemento, ou extrair uma
subcoleção e concatenar duas listas. Observe a consulta Q14:
Q14: first (select struct (professor : f.nome.unome,
salario : f.salario) from f in professor order by
f.salario desc)
Fórmula 9: Q14: operador first em uma coleção list que contém os salários dos professores em
ordem decrescente de salário Fonte: ELMASRI, 2005.
A OQL 14 mostra o operador first em uma coleção list que contém os salários dos professores
em ordem decrescente de salário. Então, o primeiro elemento dessa lista ordenada contém o
professor com o maior salário. Neste caso, o resultado mostra um membro da faculdade que
ganha o maior salário.
Esta consulta Q15 recupera os três melhores alunos que se especializam em ciência da
computação, considerando o mdc;
Q15: (select struct (sobrenome : s.nome.unome,
primeiro_nome: s.nome.pnome, mdc: s.mdc)
from s in departamentocc.forma_especialistas order by
mdc desc) [0:2];
72
Formula 10: Q15: recupera os três melhores alunos que se especializam em ciência da
computação, considerando o mdc Fonte: ELMASRI, 2005.
Essa consulta select-from-order-by retorna uma lista de alunos de ciência da computação,
ordenados por mdc em ordem descendente. Sendo que o primeiro elemento de uma coleção
possui índice 0, de maneira que a expressão [0:2] retorna uma lista contendo o primeiro,
segundo, e o terceiro elemento.
A cláusula group by da OQL, é bem parecida com da SQL, só que ela fornece uma referência
explícita à coleção de objetos em cada grupo ou partição. Observe a Q16:
Q16 : select struct (nomedepto,
numero_de_especialistas : count (partition)) from s
in alunos group by nomedepto :
s.especializa_em.dnome;
Fórmula 11: Q16: Operador de agrupamento. Retorna o número de alunos em cada
departamento Fonte: ELMASRI, 2005.
O resultado é do tipo set<struct> (nomedepto: string, partition: bag <struct> (s:Aluno)>)>, que
contém uma estrutura para cada grupo partition com dois componentes: o valor do atributo de
agrupamento (nomedepto) e a bag de objetos de aluno no grupo (partition). A cláusula select
retorna o atributo de agrupamento (nome) e a bag de objetos de aluno no grupo (partition). A
cláusula de select retorna o atributo de agrupamento (nome do departamento) e uma
contagem do número de elementos em cada partição (ou seja, o número de alunos em cada
departamento), na qual partition é a palavra-chave utilizada para se referir a cada partição.
Conclusão:
É possível implementar um sistema de complexo usando um SGBD Orientado a Objetos. A
manipulação de objetos nativamente, aumenta a performance e os ganhos de desempenho de
linguagens orientadas a objeto como o Java e as linguagens da plataforma .NET. Permite maior
desempenho e redução no tempo de desenvolvimento do software, já que não é necessário
traduzir o modelo orientado a objeto para um modelo relacional, eliminando a complexidade
extra e a perda de performance com a conversão para outros formatos como SQL. Uma outra
vantagem desse banco é de não precisar de um DBA, pois sua administração é de
responsabilidade do próprio analista de sistemas.
Por ser uma tecnologia nova, muitas empresas preferem não arriscar, pois o modelo relacional
ainda é muito empregado nos dias atuais. Migrar de uma tecnologia bem difundida no mercado
para uma que está apenas começando seria muito arriscado. Essa é uma das desvantagens do
BD OO. O que ocasiona poucas aplicações nessa nova tecnologia. Muitos ainda não confiam na
sua integridade. À medida que a complexidade for aumentando, as empresas vão cada vez mais
buscar por alternativas que consigam adequar às suas necessidades.
XI.6. ATIVIDADE XI
Data WareHouse Pode ser traduzido como “depósito de dados”. Sua função principal é o
armazenamento de informações de um banco de dados referente a uma ou mais atividades de
uma empresa de forma consolidada, voltada à tomada de decisões. É como um agrupamento
inteligente de dados de uma mesma fonte, como: origem, formato, nomes, tipo de negócio,
regras, conexões entre outros. Este princípio é muito discutido quando relacionado a BI
(Business Intelligence). Tudo isso favorece um resultado completo ao usuário, sem a
necessidade de executar várias consultas (relatórios), cruza-las e finalmente chegar a um
resultado. Em Data Warehouse os relatórios são exibidos dinamicamente de acordo com a
necessidade focando pontos estratégicos. Seu objetivo é trabalhar com uma grande quantidade
de informação e principalmente dados históricos. Estamos falando de sistemas transacionais
(OLTP), que, de uma forma bem ampla, são sistemas responsáveis por registrar todos os
acontecimentos de uma organização. Resumindo, são os acontecimentos históricos que nos
levam a uma melhor tomada de decisão e à prevenção de eventos futuros. Esses dados estão no
Data Warehouse. Por definição esses dados armazenados não mudam, exatamente por serem
dados históricos, salvo quando é necessário executar correções em alguma informação
específica. Um detalhe importante é que esses dados estão disponíveis somente para consulta.
Uma base modificável deixa de ser uma Data Warehouse. O que faz a leitura dessa base
histórica e inalterável é chamado de OLAP, nada mais do que um processador das informações
contidas na Data Warehouse. É através dele que o usuário consegue visualizar os resultados
palpáveis através de relatórios consistentes e inteligentes (a possibilidade de tomada de decisão
descrita acima).
O assunto DW é constantemente tratado na literatura devido a sua importância estratégica
dentro da empresa, na medida em que proporciona a tomada de decisão apoiada em dados
confiáveis e de fácil acesso. "Há décadas, as empresas tem sistematicamente coletado dados
operacionais através de seus sistemas OLTP (Online Transaction Processing Systems). Mas na
maioria dos casos, não houve preocupação com a integração entre as fontes de dados e com o
tratamento dos dados históricos".
Por outro lado, a metodologia e os mecanismos utilizados em projetos de interface
Homem/Máquina eram limitados a terminais orientados a caracteres até o surgimento das GUI
(Interfaces gráficas). Além da interface gráfica, novas tecnologias orientadas a objeto como
ActiveX e OLE disponibilizaram novos e poderosos recursos para a construção de interfaces HM.
A tecnologia de software componente interoperável apresenta os componentes como objetos
distribuídos que suportam a compatibilidade com interfaces binárias de intercomunicação. A
chave para o software componente é definir as interfaces entre os componentes e deixar o
construtor do componente escolher o melhor caminho para construí-lo de acordo. Desta forma,
OLE (Object Linking and Embeding) é um recurso importante para o projeto e implementação
de interfaces, pois permite a utilização de objetos não relacionados, que trocam informações
sem terem sido explicitamente programados para suportar uns aos outros.
"A interface ser humano-computador, normalmente chamada interface com o usuário, é a porta
de entrada para uma aplicação de software interativa". O valor de um DW está na qualidade das
decisões que ele suporta. Ferramentas poderosas de análise de informações nas áreas de OLAP
75
(Online Analytical Processing) e Data Mining, quando incorporadas a uma arquitetura de DW,
aumentam a competitividade das empresas.
XII.3. OLAP
OLAP – On line analytical processing (Processamento analítico on-line) designa uma ferramenta
que oferece um método de acessar, visualizar e analisar uma gama de dados corporativos com
alta flexibilidade e performance, visando oferecer relatórios gerenciais que servirão como
instrumento de apoio a decisões corporativas.
Ela se baseia no uso de dados consolidados que serão armazenados para criação futura de
cubos e posterior análise deles. Tais cubos armazenam valores quantitativos ou medidas, que,
por sua vez, são identificadas por duas ou mais categorias descritivas denominadas dimensões,
compondo a estrutura do cubo.
A utilização desses cubos proporciona uma análise multidimensional das informações, ou seja,
permite que um mesmo fato seja visto de diferentes ângulos. Por exemplo, um cubo que
contenha informações sobre vendas de uma empresa pode ser composto de diversas
dimensões, como tempo, região, produto, cliente e medidas (valor de venda, unidades vendidas,
custos, margem, etc). Cada dimensão ainda pode ser subdividida em níveis. No caso, a
dimensão região poderia conter os níveis país, região, estado e cidade. Ficam, assim, garantidas
pesquisas complexas e análises comparativas.
A ferramenta OLAP tem a capacidade de efetuar algumas operações que acabam tornando-se
características desse tipo de recurso, as quais são ótimos mecanismos de agilização e
flexibilização de consultas. São elas drill across, drill down, drill ip, drill throught e sice and dice,
esta última é responsável por modificar a posição de uma informação, trocar linhas por coluna,
facilitando a compreensão dos usuários, girando o cubo sempre que houver necessidade.
Características da análise OLAP:
Drill Across: ocorre quando o usuário pula um nível intermediário dentro de uma mesma
dimensão. Por exemplo: a dimensão tempo é composta por ano, semestre, trimestre, mês e dia.
O usuário estará executando um Drill Across quando ele passar de ano direto para semestre ou
mês.
Drill Down: ocorre quando o usuário aumenta o nível de detalhe da informação, diminuindo o
grau de granularidade.
Drill Up: é o contrário do Drill Down, ele ocorre quando o usuário aumenta o grau de
granularidade, diminuindo o nível de detalhamento da informação.
Drill Throught: é quando o usuário passa de uma informação contida em uma dimensão para
uma outra. Por exemplo: Estou na dimensão de tempo e no próximo passo começo a analisar a
informação por região.
Slice and Dice: é uma das principais características de uma ferramenta OLAP. Como a
ferramenta OLAP recupera o microcubo, surgiu a necessidade de criar um módulo que
convencionou-se de Slice and Dice para ficar responsável por trabalhar esta informação. Ele
serve para modificar a posição de uma informação, alterar linhas por colunas de maneira a
facilitar a compreensão dos usuários e girar o cubo sempre que tiver necessidade.
Alertas: são utilizados para indicar situações de destaque em elementos dos relatórios,
baseados em condições envolvendo objetos e variáveis. Servem para indicar valores mediante
condições, mas não para isolar dados pelas mesmas.
Ranking: permite agrupar resultados por ordem de maiores / menores, baseado em objetos
numéricos (Measures). Esta opção impacta somente uma tabela direcionada (relatório) não
afetando a pesquisa (Query).
77
Filtros: Os dados selecionados por uma Query podem ser submetidos a condições para a leitura
na fonte de dados. Os dados já recuperados pelo usuário podem ser novamente “filtrados” para
facilitar análises diretamente no documento.
Sorts: servem para ordenar uma informação. Esta ordenação pode ser customizada, crescente
ou decrescente.
Breaks: servem para separar o relatório em grupos de informações (blocos). Por exemplo: O
usuário tem a necessidade de visualizar a informação por cidades, então ele deve solicitar um
Break. Após esta ação ter sido executada, automaticamente o relatório será agrupado por
cidades, somando os valores mensuráveis por cidades.
O IBExpert oferece uma ferramenta OLAP para ser usada com os resultados de qualquer Query
que tenha sido executada dentro da IDE do IBExpert.
A figura e código abaixo representa uma visualização no cubo de decisão, baseada no resultado
da Query executada. Para acessar a ferramenta, basta executar qualquer query, e na tela de
apresentação do resulta, clicar no botão com o ícone de um cubo, na barra de botões.
select cli.customer, c.country, c.currency, vend.total_value,
vend.order_date
from customer cli
inner join country c on (cli.country = c.country)
inner join sales vend on (cli.cust_no = vend.cust_no)
Data Mining é um termo em inglês que quer dizer mineração de dados e é empregada como
sinônimo de extração de informações implícitas constantes de base de dados, sendo muito
usada como ferramenta de apoio a decisões.
Esse assunto vem ganhando atenção de muitas áreas de interesse, sejam comerciais ou
científicas, pois todos os dias são armazenadas milhares de informações em meios eletrônicos,
com tendência a esse número crescer exponencialmente, e as empresas em geral estão
interessadas em buscar tecnologias e ferramentas que extraiam informações úteis desses dados
de forma a se ter acesso a elementos valiosos que contribuirão na competitividade entre as
empresas, bem como em seus resultados. Várias tendências, como a economia crescente
baseada em serviços, personalização em massa e crescente importância da informação é que
vêm influenciando no aumento da importância da informação sob o enfoque da
competitividade.
Apesar de essa coleta de dados e posterior análise poder ser feita manualmente, são atividades
lentas, em razão do volume de dados que cresce exponencialmente, além de serem caras e com
tendências pessoais. Por isso, tem-se buscado utilizar outras técnicas para a realização dessa
tarefa. A utilização do Data mining ainda é um campo pouco explorado devido ser uma
concepção desconhecida e ainda requer muita pesquisa e desenvolvimento, dessa forma, é um
campo promissor para aqueles profissionais de tecnologia da informação que se identificam
com o assunto de banco de dados e com essa área emergente de extração de conhecimento de
dados.
A utilização de data mining busca permitir que as empresas aumentem suas operações de
marketing, de vendas e de apoio aos clientes.
Basicamente os autores dividem o processo de descoberta do conhecimento utilizando a
técnica de data mining nos seguintes estágios: seleção dos dados, pré-processamento,
transformação, data mining propriamente dito, interpretação e avaliação. Sendo que a fase
79
“data mining” se preocupa com a extração de padrões dos dados, utilizando algoritmos de
procura.
Grandes empresas já vêm aplicando essa ferramenta como instrumento de suporte a tomada de
decisões, como Lojas Brasileiras, Wal-Mart, Bank of America, entre tantas outras.
tabelas e suas relações, uma linguagem de manipulação e definição de dados, que são
estruturas de tabulação de dados, fugindo do conceito dos documentos, que são estruturas
livres, com dados autocontidos e autodescritivos.
Os bancos orientados a documentos surgiram devido a dificuldades do SQL de se lidar com
bancos de dados gigantescos e com diversos tipos de documentos.
Um movimento chamado de noSQL fomentou o desenvolvimento de algumas tecnologias para
ligar com bases de dados "super poderosas".
Algumas iniciativas de projetos open-source criaram padrões de bancos nosql como:
MongoDB é um banco de dados orientado a documentos de alta performance, open source e
schema-free, escrito em C++ e CouchDB é um banco de dados Orientado a Documentos que
funciona bem com a linguagem Ruby.
Grandes empresas também criaram suas tecnologias para melhorar os resultados de bancos
relacionais tradicionais ou orientados a objetos:
Google Bigtable - Usado para armazenar bases de dados com n petabytes de dados e muito
rápido. Armazenamento em coluna e não em linhas com os bancos relacionais.
Amazon Dynamo (Sistema de armazenamento distribuído com processamento em cluster)
Hadoop (Pataforma Java para aplicações distribuídas criada pelo Yahoo). O Facebook também
usa esta plataforma.
Cassandra (Criado pelo Facebook baseado no Dynamo e Bigtable)
Estas tecnologias foram desenvolvidas para atender a alta demanda de consultas, volumes de
dados e principalmente para garantir melhor disponibilidade.
A principal característica destes bancos é a implementação de diversos algoritmos de
indexação/busca que permita alta performance mesmo com grandes volumes de dados e
diversos tipos de documentos.
Modelagem de Dados:
Os BDODs utilizam o conceito de dados e documentos autocontidos e autodescritivos, isso
implica que o documento em si já define como ele deve ser apresentado e o significado dos
dados em cuja sua estrutura estão armazenados. Os autores explicam que o conceito de dados
autocontidos ajudam a entender como se dá a modelagem orientada a documentos e utilizam o
exemplo de uma nota fiscal para mostrar como funcionam os documentos no mundo real. Em
um documento fiscal, todas as informações sobre uma transação já estão lá contidas: nome do
tomador do serviço, dados do prestador do serviço, data de prestação, serviços efetuados, entre
outras. Não há nenhuma referência abstrata para um outro pedaço de papel que indique o
nome do prestador do serviço ou o nome os itens que compõem aquela nota fiscal. Mesmo
assim, esta é a forma como os dados são armazenados em um banco de dados relacional: cada
nota fiscal é gravada em uma tabela tal que suas tuplas referenciem outras tuplas em outras
tabelas, onde teríamos uma tupla para as informações do prestador de serviço, uma para o
tomador do serviço, outra para cada item cobrado e assim por diante. Os autores deixam claro
que muitas vezes a forma como o modelo deve ser projetado, de acordo com seu paradigma,
muitas vezes não refletem a forma como um desenvolvedor gostaria de ter seus dados
armazenados.
A forma como os dados são modelados em BDODs permitem que haja redundância e
inconsistência dos dados, sem que haja nenhuma camada semântica para permitir o acesso a
uma única versão de um dado.
81
HÁ ainda, outra forma de modelagem de dados baseada em: uma pilha de cartões de visita. Da
mesma forma que uma nota fiscal, um cartão de visita contém todas as informações
importantes em um único documento. A maioria dos cartões de visita contém as mesmas
informações: a identificação de uma pessoa, sua afiliação e informações de contato. A diferença
principal é que o cartão de uma pessoa A pode conter o número do seu telefone celular,
enquanto de uma pessoa B, somente seja informado um telefone fixo. Como a pessoa B não
informou o número de um telefone celular, ela não tem a necessidade de tornar isso explícito,
escrevendo no cartão algo como “Telefone Celular: nenhum”. Ao invés, por simplesmente omitir
esta informação, a pessoa já está declarando que não possui um contato deste tipo disponível.
Observa-se logo, que documentos do mundo real tendem a variar de forma similar na
semântica dos dados, ou seja, o tipo de informação que estes documentos apresentam. Porém,
a sintaxe com a qual as informações são apresentadas, ou seja, sua estrutura, pode variar
enormemente. Em face ao exposto, conclui-se que enquanto num modelo relacional tradicional
é necessário que os dados estejam modelados antes de serem utilizados, em um BDOD livre de
esquema, os documentos estão prontos para agregarem informações após serem criados,
exatamente da mesma forma como é feita com os documentos do mundo real. Desta forma, os
documentos estão preparados para a evolução natural dos dados. Esta evolução pode ser
exemplificada quando uma pessoa com um cartão de visitas risca um número desatualizado e
escreve a informação mais atual, “evoluindo” os dados do documento.
Estado Global de Recursos:
Durante o processo de modelagem relacional, uma das premissas é a identificação única de
registros. A chave natural é a coleção de colunas que identificam uma tupla como única dentro
de uma tabela e que uma forma de facilitar a criação de chaves únicas em uma tupla, ao invés
da utilização de chaves naturais está na atribuição de um identificador numérico único para
cada tupla. A maioria dos bancos de dados relacionais provê estruturas chamadas de sequences,
que podem atribuir automaticamente estes identificadores numéricos a uma tupla. O principal
problema das sequences é que elas representam um estado global compartilhado, ou seja, a fim
de atribuir um identificador numérico para uma tupla, a obtenção do valor desta entidade deve
ser realizada de forma seqüencial, com um único acesso por vez. Isso se torna um problema
quando há dois bancos de dados em redes distintas que necessitam realizar uma atualização
concorrente de dados, pois não há uma forma de ambos os bancos saber em qual será o
próximo valor a ser atribuído. Surge então o conceito que “em uma arquitetura sem nada
compartilhado (shared-nothing architecture) não há um estado ou valor próximo”, pelo fato que
nenhum estado global é armazenado entre os bancos, ou seja, cada instância toma decisões
baseadas somente no seu estado atual.
Para contornar o problema das sequences, os BDODs podem utilizar o conceito de Universally
Unique Identifiers (Identificadores Únicos Universais, ou somente UUID), onde a possibilidade de
acidentalmente utilizar um mesmo identificador que outro banco de dados é efetivamente zero.
Os UUIDs são atribuídos como identificadores do documento, que devem ser únicos dentro de
um BDOD. Caso o usuário ache necessário atribuir uma chave natural a um documento, ele deve
utilizar campos específicos e armazená-los dentro do documento.
No que concerne a melhorias em relação aos bancos de dado relacionais, o conceito de UUID
não apresenta muita utilidade. O importante é entender que em BDODs não será necessário
consultar os documentos através de um identificador, já que estes oferecem métodos
avançados de agrupamento e filtragem de documentos baseado em seu conteúdo, através das
views e do MapReduce.
Um pouco sobre CouchDB:
82
Passo 1: Utilize o IBExpert versão Trial para testar o recurso de OLAP e descreva abaixo os
passos necessários para realizar Slice and dice:
84
REFERÊNCIAS
ELMASRI, R. E.; NAVATHE S. Sistemas de Banco de Dados. 6 ed., São Paulo: Pearson
Prentice Hall, 2011.
DATE, C. J. Introdução a sistemas de banco de dados. 7 ed. São Paulo: Campus, 2000.
www.devmedia.com/br acessado em 01/12/2009
www.firebase.com.br acessado em 03/01/2010
CANTU, Carlos Henrique. Firebird Essencial. Rio de Janeiro: Editora Ciência Moderna Ltda, 2005.
CANTU, Carlos Henrique. Firebird: O banco de dados do novo milênio. Rio de Janeiro: Editora
Ciência Moderna Ltda, 2006.
WATSON, John; BERSINIC, Damir. Oracle Database 10g: Certificação OCP: Guia Completo
para o Exame. Rio de Janeiro: Editora Alta Books, 2006.
THE POSTGRESQL GLOBAL DEVELOPMENT GROUP. Documentação do PostgreSQL 8.0.0. Rio
de Janeiro, 2005.
MySQL-AB. MySQL Technical Reference for Version 5.1 Including MySQL Cluster NDB
6.X/7.X Reference Guide, 2011.
TODD, Bill. Introdução a Stored Procedures e Triggers no Firebird. Artigo, 2002.
http://www.comunidade-firebird.org/modules.php?name=Downloads&d_op=getit&lid=43
acessado em 09/01/2010.
ALAN, C. Galante et al. Banco de dados Orientado a Objetos: Uma realidade. Artigo.