Informática para Ciências e Engenharias 2012/13 Teórica 10
Na aula de hoje... Introdução aos sistemas de bases de dados (parte 2): Combinar MATLAB e SQL Um exemplo prático 2
MATLAB + SQL 3
MATLAB + SQL Para combinar SQL com MATLAB, usamos uma função que corre o SQLite para executar o comando SQL que queremos. 4
SQLite na linha de comando O SQLite pode ser executado com parâmetros na linha de comando. nome do ficheiro com a base de dados. e podemos incluir também um comando SQL Na consola (cmd em Windows) sqlite3 teste.db "CREATE TABLE Massa (Simbolo TEXT, Massa REAL);" sqlite3 teste.db "INSERT INTO Massa VALUES ('H', 1);" sqlite3 teste.db "SELECT * FROM Massa;" H 1.0 5
SQLite na linha de comando O SQLite pode ser executado com parâmetros na linha de comando. um, já conhecemos, é o nome do ficheiro com a base de dados. podemos incluir também um comando SQL o que não serve de muito por si, mas pode ser útil para executar comandos SQL a partir de um programa em MATLAB. 6
SQLite na linha de comando Executar comandos SQL a partir de um programa MATLAB function result=sqlite(sql,db) Nota: esta função tem elementos que não fazem parte da matéria de ICE. 7
MATLAB + SQL 8
MATLAB + SQL Nome da base de dados se não for indicado nenhum em argumento. 9
MATLAB + SQL Troca aspas por plicas (é preciso duas dentro de uma string) 10
MATLAB + SQL Executa o sqlite3 com o comando SQL usando a função system. 11
MATLAB + SQL No Octave / MATLAB > sqlite('create TABLE Massa (Simbolo TEXT, Massa REAL);','teste.db') ans = > sqlite('insert INTO Massa VALUES ("H", 1);','teste.db') ans = > sqlite('select * FROM Massa;','teste.db') ans = H 1.0 12
Exemplo: projectos de recuperação de praias 13
praias.txt Concelho, Nome, Custo, Prioridade Marinha Grande;Esporao da Praia da Vieira;720000.00;Media Lourinha;Arribas junto ao forte do Paimogo;591000.00;Media Lourinha;Arribas em Porto das Barcas;691000.00;Media Lourinha;Arribas em Porto Dinheiro;606500.00;Media Sintra;Arribas da praia Grande do Rodizio;39951.63;Media Sintra;Arribas da praia das Azenhas do Mar;326560.08;Media... Setubal;Arribas da praia de Galapos;100000.00;Baixa... Portimao;Saneamento da arriba na praia do Vau;30000.00;Elevada 14
Objectivo Usar um sistema de gestão de bases de dados (SGBD) para gerir a informação Esquema da base de dados Utilizador/ Programador Motor da base de dados Ficheiros de suporte da base de dados 15
Modelo relacional Registo (objecto, entidade) Conjunto de campos (atributos) relacionados análogo da estrutura no Matlab Tabela Um conjunto de registos. Análogo ao vector de estruturas no Matlab Um registo por linha, um atributo por coluna Base de dados Relacional Um conjunto de tabelas relacionadas. As chaves permitem relacionar tabelas. 16
Modelo relacional Registo (objecto, entidade) Conjunto de campos (atributos) relacionados análogo da estrutura no Matlab Tabela Um conjunto de registos. Análogo ao vector de estruturas no Matlab Um registo por linha, um atributo por coluna Base de dados Relacional Um conjunto de tabelas relacionadas. As chaves permitem relacionar tabelas. Em ICE vamos só abordar esta parte. 17
Objectivo Criar tabela Inserir dados dos projectos de recuperação Questionar a BD usando SQL Exemplo: obter os projectos de prioridade alta, média e baixa. 18
Criar tabela function criatabela(nomebd) 19
20
Porquê PRIMARY KEY? Numa base de dados relacional, as chaves permitem relacionar tabelas diferentes. (Não vamos usar BDs com várias tabelas). Mas mesmo só com uma tabela é útil poder identificar inequivocamente cada registo por exemplo, para evitar a inserção de duplicados neste caso assumimos que dois projectos com o mesmo nome seria um erro 21
Porquê PRIMARY KEY? O SQLite cria sempre um atributo chamado Rowid que identifica inequivocamente cada registo, mesmo que não se crie uma chave primária. No entanto, esse não serve para evitar registos repetidos porque incrementa automaticamente. 22
Testes podemos começar por criar uma tabela numa BD de teste, para podermos testar a função que carrega os dados. octave:23> criatabela('teste.db'); octave:24> sqlite('.tables','teste.db') ans = Projectos 23
Carregar os dados function carregapraias(nomefich, nomebd) 24
25
Lê cada linha do ficheiro de entrada. 26
Cria o comando SQL de inserção tabela. A função sprintf funciona como fprintf mas devolve uma string. 27
Executa o comando SQL na BD especificada. 28
Testar: (podemos fazer tudo no MATLAB/Octave) octave:12> carregapraias('praias.txt', 'teste.db') octave:13> sqlite('select * from Projectos;','teste.db') ans = Marinha Grande Esporao da Praia da Vieira 720000.0 Media Lourinha Arribas junto ao forte do Paimogo 591000.0 Media Lourinha Arribas em Porto das Barcas 691000.0 Media Lourinha Arribas em Porto Dinheiro 606500.0 Media Sintra Arribas da praia Grande do Rodizio 39951.63 Media Sintra Arribas da praia das Azenhas do Mar 326560.08 Media Sintra Arribas da praia Pequena 428015.58 Media... 29
LIKE octave:29> sqlite('select Nome FROM Projectos WHERE Nome LIKE "Arriba%";','teste.db') ans = Arribas junto ao forte do Paimogo Arribas em Porto das Barcas Arribas em Porto Dinheiro Arribas da praia Grande do Rodizio Arribas da praia das Azenhas do Mar Arribas da praia Pequena Arriba da Praia Fonte do Cortico Arribas da praia de Galapos 30
LIKE octave:32> sqlite('select Nome FROM Projectos WHERE Nome LIKE "%praia%";','teste.db') ans = Esporao da Praia da Vieira Arribas da praia Grande do Rodizio Arribas da praia das Azenhas do Mar Arribas da praia Pequena Arriba da Praia Fonte do Cortico Relocalizacao de acessos das praias de Morgavel, Franquia e Farol Arribas da praia de Galapos Alimentacao artificial da praia da Mareta Saneamento da arriba na praia do Vau 31
DISTINCT octave:33> sqlite('select Concelho FROM Projectos;','teste.db') ans = Marinha Grande Lourinha Lourinha Lourinha Sintra Sintra Sintra Santiago do Cacem Sines Setubal Vila do Bispo Portimao 32
DISTINCT > sqlite('select DISTINCT Concelho FROM Projectos;','teste.db') ans = Marinha Grande Lourinha Sintra Santiago do Cacem Sines Setubal Vila do Bispo Portimao 33
DISTINCT > sqlite('select DISTINCT Prioridade FROM Projectos;','teste.db') ans = Media Baixa Elevada 34
Problema: o resultado do sqlite é uma string mas convém estruturar melhor a informação ans = Marinha Grande Esporao da Praia da Vieira 720000.0 Media Lourinha Arribas junto ao forte do Paimogo 591000.0 Media Lourinha Arribas em Porto das Barcas 691000.0 Media Lourinha Arribas em Porto Dinheiro 606500.0 Media Sintra Arribas da praia Grande do Rodizio 39951.63 Media Sintra Arribas da praia das Azenhas do Mar 326560.08 Media Sintra Arribas da praia Pequena 428015.58 Media... 35
Converter a string do resultado num vector de estruturas function recs=parserecords(sqlresult,namestring) Nota: esta função tem elementos que não fazem parte da matéria de ICE. 36
37
Lista os nomes dos campos das estruturas, ou nada se nenhuma string for fornecida no segundo argumento. 38
Parte a string pelas linhas, percorre as linhas partindo pelo separador (' '). 39
Para cada atributo (coluna da tabela) gerar ou obter o nome do campo da estrutura, converter em número se possível e guardar no vector de estruturas. 40
Obter nome e custo de projectos com uma prioridade especificada. function projs=selprioridade(tabela, basedados, prioridade) 41
A função sprintf funciona como fprintf mas em vez de escrever num ficheiro ou consola devolve a string formatada 42
Obtido o resultado da função sqlite (numa só string), convertemos num vector de estruturas com parserecords, indicando os nomes dos campos: nome e custo. 43
Testar: octave:19> elevada=selprioridade('projectos', 'teste.db', 'Elevada'); octave:20> elevada(1) nome = Alimentacao artificial da praia da Mareta custo = 2500000 octave:21> elevada(2) nome = Saneamento da arriba na praia do Vau custo = 30000 octave:22> baixa=selprioridade('projectos', 'teste.db', 'Baixa') baixa = nome = Arribas da praia de Galapos custo = 100000 44
Função principal: function [elevada,media,baixa]=processaprojs(fich, basedados) 45
46
Testar: octave:25> [elev,med,baix]=processaprojs('praias.txt','praias.db') elev = 1x2 struct array containing the fields: nome custo med = 1x9 struct array containing the fields: nome custo baix = scalar structure containing the fields: nome = Arribas da praia de Galapos custo = 100000 47
Testar: octave:26> elev.nome ans = Alimentacao artificial da praia da Mareta ans = Saneamento da arriba na praia do Vau octave:27> med.nome ans = Esporao da Praia da Vieira ans = Arribas junto ao forte do Paimogo ans = Arribas em Porto das Barcas ans = Arribas em Porto Dinheiro ans = Arribas da praia Grande do Rodizio ans = Arribas da praia das Azenhas do Mar ans = Arribas da praia Pequena ans = Arriba da Praia Fonte do Cortico ans = Relocalizacao de acessos das praias de Morgavel, Franquia e Farol 48
Bónus: gráfico de barras 49
Gráfico dos custos A partir do vector de estruturas com um conjunto de projectos (nome e custo) desenhar um gráfico de barras dos custos. 50
Gráfico dos custos função bar, com vector bar([1,2,3,4,3,2,1]) 51
Gráfico dos custos função bar, com matriz Bar([1,3,2;2,4,5;1,1,4]) 1 3 2 2 4 5 1 1 4 52
Gráfico dos custos A partir do vector de estruturas com um conjunto de projectos (nome e custo) desenhar um gráfico de barras dos custos. function grafico(projectos) 53
Gráfico dos custos 54
Gráfico dos custos Testar octave:29> grafico(med) 55
Trabalho prático 2 56
Trabalho prático 2 Semelhante ao exemplo desta aula criar tabela numa base de dados com SQLite processar ficheiros e carregar tabela obter registos da tabela fazer gráfico Entrega dia 26 de Maio versão preliminar no dia 19 de Maio discussões na última semana de aulas 57
Dúvidas 58