View
218
Download
0
Embed Size (px)
Citation preview
Programação em Bancos de Dados Relacionais
Programando em SGBDs Relacionais
• Nem toda tarefa é factível em SQL• SQL – Linguagem de Consulta, não de
Programação• SQL não implementa, de fato, uma
Máquina de Turing completa!• Linguagens de programação (C, Pascal,
Cobol, Fortran, Lisp, Prolog): Máquinas de Turing!
Exemplo
• Suponha uma tabela Projeto, criada da seguinte forma:
Create table Projeto (Cod int primary key,Titulo Varchar(20) not null unique,CodProjPai int references Projeto)
• Um projeto pode ser parte de outro projeto (um projeto maior)
• Um projeto pode ser subdividido em outros
Desafio:
• Crie uma consulta em SQL que, dado o projeto de código 14, mostre todos os seus descendentes.
• Ou então os seus ascendentes.• !• ?• Impossível! SQL não faz tudo o que uma
Linguagem de Programação faz!
Como resolver?
• Os SGBDs Relacionais acrescentam linguagens de programação à SQL
• É possível fazer-se estruturas programáticas (procedimentos) nos SGBDRs
• Isso serve para resolver a incompletude de SQL bem como implementar parte das regras de negócio!
Regras de negócio
• Cliente/Servidor: – Processa no cliente a interface e (parte das)
regras de negócio– Processa no servidor (parte das) regras de
negócio e acesso a dados• Isso torna o cliente muito caro!
– Robustez para suportar o processamento– Alto custo de reinstalação/upgrade dos sistemas
A solução
• Cliente executando apenas interface (cliente magro)– Fácil de ser reinstalado– Menor capacidade de processamento
• Regras de negócio num servidor centralizado
• Dados idem!
Possíveis caminhos
• Um servidor de aplicações– Regras de negócio implementadas em
componentes– Compartilhadas pelos clientes– Atualizações e manutenções centralizadas– Disponíveis em serviços como Web Services
Possíveis caminhos
• Procedimentos armazenados– Regras de negócio implementadas em
componentes– Compartilhadas pelos clientes– Atualizações e manutenções centralizadas– Disponíveis no próprio SGBD!– Procedimentos armazenados
Qual a melhor?
• Servidor de aplicações:– Maior independência de plataforma– Dificuldade de integração Dados/Programas
• Procedimentos Armazenados– Total dependência de plataforma (SGBD)– Facilidade de integrar Dados e Programas
(linguagens nativas)
Os caminhos
• De um modo geral opta-se pelo servidor de aplicações– A integração pode ser facilitada por ferramentas– O valor agregado pela Independência de
plataforma é muito alto!• Mas há motivos para escolher
Procedimentos Armazenados!
Porque Procedimentos Armazenados
• Fácil desenvolvimento• Cultura de uso de um SGBD• Implementação de partes do processamento
– Não há obrigação de escolher entre Procedimentos Armazenados e Servidores de Aplicação
– Normalmente encontra-se uma solução híbrida!
Procedimentos Armazenados
• O que é– Uma estrutura de programa acionável a partir
do cliente ou do próprio servidor– Pode receber parâmetros– Executa alguma tarefa no SGBD (Transações)– Busca algum dado no SGBD
O primeiro procedimento armazenado
• Um modelo em UML• Um Diagrama de Colaboração• Uma chamada do tipo:
AlunosJanela
Cadastro Alunos
Novo(Aluno)CadAluno( )
Secretária
Como implementa• O método CadAluno ( )• Cliente: só interface
Como Implementa
• O Método Novo( )• SGBD• Os parâmetros serão os dados dos alunos!• Chamado pela Janela Cadastro de Alunos!• Duas soluções:
a) Insert into alunos (...)b) Exec NovoAluno(...) /* Transact Sql */
• Qual a melhor?
Acoplamento
• O quanto um componente A do programa interfere num componente B?– Componente: Um método, uma classe, uma
tabela, uma janela, um arquivo, etc.– Interferir: Mudar algo em A torna necessário
alterar também B? E o contrário?
Acoplamento
• À medida de o quanto alterações de um componente impactam em outro denomina-se Acoplamento!
• Obs: – Não é necessário quantificar o acoplamento!– Deve-se buscar acoplamentos os mais baixos
possíveis!
No nosso exemplo
• Onde há mais acoplamento?• Suposição: Mudou o nome de uma coluna
na tabela Alunos– Em a): Todos os locais onde a chamada é feita
precisam ser modificados– Em b): Somente a implementação do
procedimento NovoAluno precisa ser modificada – o cliente não “vê” nada!
Como fazer um procedimento Armazenado
• Comando DDL• Ex: (Transact SQL)Create procedure NomeProc <Parametros> as<Comandos>
• Em qualquer SGBDR é possível criar procedimentos
• Os conceitos são os mesmos!
Exemplo de Procedimento
Create procedure AlteraPreco as @CodProd int, @NovoPreco as numeric as
Update EstoqueSet Preco = @NovoPrecoWhere Cod = @CodProd;
Pode-se definir uma transaçãoCreate procedure Transfere @ct_origem char(6),
@ct_dest as char(6), @valor as numeric asBegin transaction
update contas set saldo = saldo - @valorwhere num = @ct_origem;update contas set saldo = saldo + @valorwhere num = @ct_dest;
Commit;
Pegando um dado p/ variável local
Create procedure Transfere @ct_origem char(6), @ct_dest as char(6), @valor as numeric as
Declare @saldo as numeric;Select @saldo = saldoFrom contasWhere Num = @ct_origem;
...
Usando comandos de fluxo: ifCreate procedure Transfere @ct_origem char(6),
@ct_dest as char(6), @valor as numeric asDeclare @saldo as numeric;
Select @saldo = saldoFrom contasWhere Num = @ct_origem;...if @saldo < 0 /* não é permitido *
...
Pode-se encerrar transações com RollBack
Create procedure Transfere @ct_origem char(6), @ct_dest as char(6), @valor as numeric as
Begin transactionDeclare @saldo as numeric;update contas set saldo = saldo - @valorwhere num = @ct_origem;update contas set saldo = saldo + @valorwhere num = @ct_dest;Select @saldo = saldo From contasWhere Num = @ct_origem;if @saldo < 0 /* não é permitido */
rollback;else
Commit;
Procedimentos podem retornar dados
• Outro exemplo
AlunosJanela
Cadastro Alunos
C = PegaMedia(Aluno)MediaAluno( )
Secretária
Como chamar?
• Num ambiente externo (cliente)Exec PegaMedia ‘19921414’– Retorna dados que devem ser tratados
(Datasets, Recordsets, etc.)• No mesmo ambiente
Exec @Media=PegaMedia ‘19921414’– Semelhante ao uso de select com variáveis
locais
Triggers (Gatilhos)
• Há situações em que se pode adaptar um procedimento armazenado a um evento
• Certas regras de integridade não podem ser implementadas na criação da tabela
• Ex:– Como impor uma restrição de integridade com
cardinalidade 1 para 30?
Situando o exemplo
• Numa universidade, só podem haver no máximo 30 alunos numa turma
• Tabela Turma (CodDisc$, MatAluno$)• Pode-se fazer um trigger que conte a
quantidade de alunos matriculados– Se for inferior ao limite, tudo ok– Se for superior ao limite, operação cancelada
(rollback)
Eventos
• Triggers estão associados a eventos transacionais– Insert: o trigger executa associado a uma
operação de inclusão numa tabela– Update: o trigger executa associado a uma
operação de alteração numa tabela– Delete: o trigger executa associado a uma
operação de exclusão numa tabela
Como criar um Trigger
• Comando DDL• Ex: (Transact SQL)Create trigger NomeTrigger on Tabela for [insert, update, delete] as
<comandos>• Em qualquer SGBDR é possível criar
procedimentos• Os conceitos são os mesmos!
Nosso exemploCreate trigger tg_turmas_iu on turmas for insert, updateAsDeclare @quant as int;Select @quant = count(*) from turmas t, inserted iWhere t.CodDisc = i.CodDisc;If @quant > 30 /* Limite máximo */Begin
raiserror(‘Turma com limite máximo’,16,1);rollback;
End;
• Raiserror: retorna uma mensagem de erro (Transact Sql)
Inserted
• Tabela Virtual• Para manipular os dados que estão sendo
incluídos na tabela• Possui as mesmas colunas da tabela
Deleted
• Tabela Virtual• Para manipular os dados que estão sendo
excluídos da tabela• Possui as mesmas colunas da tabela
Dados Novos e Velhos• Inserted são os dados “novos” (entrando)• Disponíveis nos triggers associados a
– Insert– Update
• Deleted são os dados “velhos” (saindo)• Disponíveis nos triggers associados a
– Delete– Update
Cursores
• Mais um exemplo
AlunosAlunos *(Para cada aluno A de computação) FazMatricula(A)
Como implementar?
• FazMatricula é um procedimento armazenado– Recebe como parâmetro a matrícula de um
aluno (identificador de um aluno)• Para implementar a chamada aos múltiplos
valores:• Cursores
O que é um cursor
• Uma lista de dados• Resultantes de um comando select• Podem ser processados separadamente• Podem ser atribuídos a uma (ou mais)
variáveis• Precisam ser declarados, abertos, fechados e
desalocados!
Como se usa
Declare NomeCursor cursor for select ...– Declara um cursor
Open NomeCursor– Abre o cursor (executa a consulta)
Fetch NomeCursor into <variáveis>– Traz um dado do cursor para variáveis (é
necessário compatibilidade de tipos)
Como se usaClose NomeCursor
– Fecha o cursorDeallocate NomeCursor
– Desaloca o cursor (libera a área)• @@Fetch_Status: uma variável de ambiente cujo
valor depende do resultado do último Fetch– Zero se não retornou dados– Diferente de zero se retornou
• @@Fetch_Status é Transact SQL• Nos outros SGBDs há soluções similares
Usando um cursor...Declare cs_alunos cursor for select matricula from
alunos;Declare @matr as char(11);Begin transaction /* uma transação muito longa */Fetch cs_alunos into @matr;While @@Fetch_Status <> 0 /* comando de fluxo */
beginexec FazMatricula @matr;Fetch cs_alunos into @matr;end;
Commit;Close cs_alunos;Deallocate cs_alunos;...
Observações especiais
• Cursores podem ter mais de um dado por linhaDeclare cs_turmas cursor for select matricula, coddisc from turmas;
...Fetch cs_turmas into @aluno, @disc;
• Pode-se e usar ao mesmo tempo quantos cursores forem necessários
Programação em SGBDs Relacionais
FIM!
“Dizes-me com quem andas e eu te direi se vou contigo”Barão de Itararé