17 - sqlite e python17 - sqlite e python17 - sqlite e python17 -...
TRANSCRIPT
-
ICE-BICE-BICE-BICE-BICE-BICE-BICE-BICE-BICE-B
17 - Sqlite e Python17 - Sqlite e Python17 - Sqlite e Python17 - Sqlite e Python17 - Sqlite e Python17 - Sqlite e Python17 - Sqlite e Python17 - Sqlite e Python17 - Sqlite e Python
Ludwig Krippahl
-
1
Sqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + Python
Resumo■ Usar Sqlite a partir de Python■ Módulo sqlite3■ Ligação à base de dados■ Cursor para executar comandos SQL■ Exemplo prático: criar uma tabela e consultar os dados
-
2
Sqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + Python
Usar Sqlite em PythonUsar Sqlite em PythonUsar Sqlite em PythonUsar Sqlite em PythonUsar Sqlite em PythonUsar Sqlite em PythonUsar Sqlite em PythonUsar Sqlite em PythonUsar Sqlite em Python
-
3
Sqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + Python
Porquê usar um motor de bases de dados?■ A linguagem SQL facilita muito algumas operações• Criar tabelas, inserir registos, consultar dados
■ O motor de bases de dados está optimizado para gerir os dados• Garante integridade da informação, mesmo em caso de falhas
• Está preparado para gerir grandes volumes de dados• Oferece uma interface standard (SQL) acessível a outros sistemas
-
4
Sqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + Python
Como usar o Sqlite em Python com o módulo sqlite3■ Criar uma ligação à base de dados: conn = connect(db_name)■ Obter um cursor, que executa SQL: cursor = conn.cursor()■ Dar o comando ou commandos SQL: cursor.execute(sql)■ Actualizar a base de dados: conn.commit()• Isto garante atomicidade das transacções
• Até ao commit() a BD não é alterada.
• Apenas parece alterada da perspectiva desta ligação
• No commit() são feitas todas as alterações.
• Se houver erro não é feita nenhuma alteração
• Se nos arrependemos, em vez do commit() podemos fazer rollback()
■ Fechar a ligação: conn.close()
-
5
Sqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + Python
Exemplo: Renovação de praiasExemplo: Renovação de praiasExemplo: Renovação de praiasExemplo: Renovação de praiasExemplo: Renovação de praiasExemplo: Renovação de praiasExemplo: Renovação de praiasExemplo: Renovação de praiasExemplo: Renovação de praias
-
6
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Temos um ficheiro de texto com dados de projectos■ Ficheiro praias.txt• Concelho, nome, custo e 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
Sintra;Arribas da praia Pequena;428015.58;Media
Santiago do Cacem;Arriba da Praia Fonte do Cortico;23000.00;Media
Sines;Relocalizacao de acessos das praias de Morgavel, Franquia ...
Setubal;Arribas da praia de Galapos;100000.00;Baixa
Vila do Bispo;Alimentacao artificial da praia da Mareta;2500000.00;Elevada
Portimao;Saneamento da arriba na praia do Vau;30000.00;Elevada
■ Queremos organizar isto numa tabela para poder consultar• Por exemplo, todos os projectos com uma certa prioridade
-
7
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Plano do programa:■ Criar a tabela Projectos com os campos necessários:• concelho, nome, custo, prioridade
■ Carregar os dados do ficheiro para a tabela Projectos■ Criar uma função que liste os projectos com a prioridade
especificada• Consultando a tabela na BD
import sqlite3 def create_table(db_name): """create the Projects table in the database""" def load_projects(file_name, db_name): """load projects from file into projects table""" def with_priority(db_name,priority): "return dictionary with projects of given priority"
-
8
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Criar a tabeladef create_table(db_name): """create the projects table in the database""" conn = sqlite3.connect(db_name) cursor = conn.cursor() cursor.execute('CREATE TABLE Projects ( Concelho TEXT, Nome TEXT,'+ 'Custo FLOAT, Prioridade TEXT, PRIMARY KEY(Nome));') conn.commit() conn.close()
■ Ligar à base de dados (connect)■ Obter o cursor para essa ligação■ Executar o código SQL para criar a tabela e fazer commit■ Fechar a ligação.
-
9
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Criar a tabeladef create_table(db_name): """create the projects table in the database""" conn = sqlite3.connect(db_name) cursor = conn.cursor() cursor.execute('CREATE TABLE Projects ( Concelho TEXT, Nome TEXT,'+ 'Custo FLOAT, Prioridade TEXT, PRIMARY KEY(Nome));') conn.commit() conn.close()
In : create_table('teste.db') In :
■ Como sabemos se funcionou?
-
10
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Como verificar o resultado■ Opção 1: usar o sqlite3 directamente:
SQLite version 3.20.1 2017-08-24 16:21:36 Enter ".help" for usage hints. Connected to a transient in-memory database. Use ".open FILENAME" to reopen on a persistent database. sqlite> .open teste.db sqlite> .tables Projects sqlite> .schema CREATE TABLE Projects ( Concelho TEXT, Nome TEXT,Custo FLOAT, Prioridade TEXT, PRIMARY KEY(Nome)); sqlite> .quit
-
11
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Como verificar o resultado■ Opção 2: usar um gestor para Sqlite.• Sqliteman (http://sqliteman.yarpen.cz/), Sqlitebrowser (https://sqlitebrowser.org/)
■ Não é necessário; usem isto apenas se acharem que dá jeito
-
12
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
■ Problema: se a tabela já existe ocorre uma exception
In : create_table('teste.db') ... OperationalError: table Projects already exists
■ Isto é inconveniente porque bloqueia a execução■ Para evitar que pare vamos usar um bloco try ... except
try: ... except ...: ...
■ Se ocorrer um erro no bloco try a execução passa ao ramoexcept que corresponde ao erro
■ Nota: pode ser todos se não especificarmos qual, mas isso é máideia.
-
13
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Criar a tabeladef create_table(db_name): """create the projects table in the database""" conn = sqlite3.connect(db_name) cursor = conn.cursor() try: cursor.execute('CREATE TABLE Projects ( Concelho TEXT, Nome TEXT,'+ 'Custo FLOAT, Prioridade TEXT, PRIMARY KEY(nome));') conn.commit() except sqlite3.Error: print('Error: could not create table.') conn.close()
In : create_table('teste.db') In : create_table('teste.db') Error: could not create table. In :
-
14
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Inserir os dados do ficheiroMarinha 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
Sintra;Arribas da praia Pequena;428015.58;Media
Santiago do Cacem;Arriba da Praia Fonte do Cortico;23000.00;Media
Sines;Relocalizacao de acessos das praias de Morgavel, Franquia ...
Setubal;Arribas da praia de Galapos;100000.00;Baixa
Vila do Bispo;Alimentacao artificial da praia da Mareta;2500000.00;Elevada
Portimao;Saneamento da arriba na praia do Vau;30000.00;Elevada
-
15
Strings e SQLStrings e SQLStrings e SQLStrings e SQLStrings e SQLStrings e SQLStrings e SQLStrings e SQLStrings e SQL
Criação de strings com outros argumentos■ Para criar comandos SQL será preciso combinar strings e
parâmetros■ Uma opção é usar format:
In : 'INSERT INTO Table VALUES( {}, "{}", {});'.format(1,'abc','NULL') Out: 'INSERT INTO Table VALUES( 1, "abc", NULL);' In : 'INSERT INTO Table VALUES( {0}, "{1}", {2});'.format(1,'abc','NULL') Out: 'INSERT INTO Table VALUES( 1, "abc", NULL);' In : 'INSERT INTO Table VALUES( {num}, "{tex}", {nul});'\ ...: .format(num=1,tex='abc',nul='NULL') Out: 'INSERT INTO Table VALUES( 1, "abc", NULL);'
■ Nota: na string com o comando SQL as strings têm de estardelimitadas
-
16
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Inserir os dados do ficheirodef load_projects(file_name, db_name): """load projects from file into projects table""" lines = open(file_name).readlines() conn = sqlite3.connect(db_name) cursor = conn.cursor() template = 'INSERT INTO Projects VALUES ( "{0}", "{1}", {2}, "{3}");' for line in lines: try: cells = line.strip().split(';') sql = template.format(cells[0],cells[1],cells[2],cells[3]) cursor.execute(sql) conn.commit() except sqlite3.Error: print('Error on ',line) conn.close()
■ Tentamos inserir cada registo e fazer logo o commit• Se alguma coisa correr mal, avisamos que houve um erro naquela linha
■ Alernativa: fazer todos os execute e depois um só commit
-
17
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Inserir os dados do ficheiro■ Testar:
In : load_projects('praias.txt','teste.db')
■ Verificar com a consola do sqlite3
SQLite version 3.20.1 2017-08-24 16:21:36 Enter ".help" for usage hints. Connected to a transient in-memory database. Use ".open FILENAME" to reopen on a persistent database. sqlite> .open teste.db sqlite> select * from projects; 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 sqlite>.quit
-
18
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
■ Testar:
In : load_projects('praias.txt','teste.db')
■ Verificar com o sqliteman• (Opcional, e é mais importante familiarizarem-se com a consola)
-
19
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Com a tabela no sqlite3 podemos:■ Ver os custos dos projectos de nome começado por Arriba:
sqlite> SELECT Nome, Custo FROM Projects WHERE Nome LIKE "Arriba%"; Arribas junto ao forte do Paimogo|591000.0 Arribas em Porto das Barcas|691000.0 Arribas em Porto Dinheiro|606500.0 Arribas da praia Grande do Rodizio|39951.63 Arribas da praia das Azenhas do Mar|326560.08 Arribas da praia Pequena|428015.58 Arriba da Praia Fonte do Cortico|23000.0 Arribas da praia de Galapos|100000.0 sqlite>
■ O operador LIKE compara strings admitindo wildcards• O sinal % na string do LIKE substitui qualquer substring
-
20
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Com a tabela no sqlite3 podemos:■ Ver os custos dos projectos com praia no nome:
sqlite> SELECT Nome, Custo FROM Projects WHERE Nome LIKE "%praia%"; Esporao da Praia da Vieira|720000.0 Arribas da praia Grande do Rodizio|39951.63 Arribas da praia das Azenhas do Mar|326560.08 Arribas da praia Pequena|428015.58 Arriba da Praia Fonte do Cortico|23000.0 Relocalizacao de acessos das praias de Morgavel, Franquia e Farol|100100.0 Arribas da praia de Galapos|100000.0 Alimentacao artificial da praia da Mareta|2500000.0 Saneamento da arriba na praia do Vau|30000.0 sqlite>
■ O operador LIKE compara strings admitindo wildcards• O sinal % na string do LIKE substitui qualquer substring
■ O operador LIKE não distingue maiúsculas e minúsculas
-
21
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Com a tabela no sqlite3 podemos:■ Ver os concelhos diferentes onde há projectos (DISTINCT)
sqlite> SELECT DISTINCT Concelho FROM Projects; Marinha Grande Lourinha Sintra Santiago do Cacem Sines Setubal Vila do Bispo Portimao
■ Ou prioridade:
sqlite> SELECT DISTINCT Prioridade FROM Projects; Media Baixa Elevada sqlite>
-
22
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Consultas usando Python■ Com o objecto cursor podemos executar o SELECT• Neste caso não há commit porque não alteramos a base de dados
■ Depois de executar o SELECT, podemos obter todos os resultadoscom cursor.fetchall()
• Uma lista de tuplos com os valores dos campos
In : conn = sqlite3.connect('teste.db') In : cursor = conn.cursor() In : cursor.execute('SELECT * FROM Projects WHERE Nome LIKE "%praia%";') In : cursor.fetchall() Out: [('Marinha Grande', 'Esporao da Praia da Vieira', 720000.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'), ... ('Portimao', 'Saneamento da arriba na praia do Vau', 30000.0, 'Elevada')] In : conn.close()
-
23
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Consultas usando Python■ Vamos criar uma função auxiliar para simplificar isto• E organizar os dados como uma lista de dicionários, usandocursor.description
• Tem um tuplo de tuplos com o nome da coluna como primeiro elemento
• O resto não interessa, é só para compatibilidade com a API de BD
• Podemos usar isto para criar uma lista de dicionários
In : conn = sqlite3.connect('teste.db') In : cursor = conn.cursor() In : cursor.execute('SELECT * FROM Projects WHERE Nome LIKE "%praia%";') In : cursor.description Out: (('Concelho', None, None, None, None, None, None), ('Nome', None, None, None, None, None, None), ('Custo', None, None, None, None, None, None), ('Prioridade', None, None, None, None, None, None)) In : conn.close()
-
24
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Consultas usando Python■ Função auxiliar para simplificar consultas
def query_db(db_name,query): "return dictionary with result of SELECT" conn = sqlite3.connect(db_name) cursor = conn.cursor() cursor.execute(query) records = cursor.fetchall() conn.close() result = [] for record in records: current = {} for ix in range(len(record)): current[cursor.description[ix][0]] = record[ix] result.append(current) return result
-
25
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Consultas usando Python■ Função auxiliar para simplificar consultas
In : query_db('teste.db','SELECT * FROM Projects;') Out[36]: [{'Concelho': 'Marinha Grande', 'Custo': 720000.0, 'Nome': 'Esporao da Praia da Vieira', 'Prioridade': 'Media'}, {'Concelho': 'Lourinha', 'Custo': 591000.0, 'Nome': 'Arribas junto ao forte do Paimogo', 'Prioridade': 'Media'}, {'Concelho': 'Lourinha', 'Custo': 691000.0, 'Nome': 'Arribas em Porto das Barcas', 'Prioridade': 'Media'}, ... {'Concelho': 'Portimao', 'Custo': 30000.0, 'Nome': 'Saneamento da arriba na praia do Vau', 'Prioridade': 'Elevada'}]
-
26
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Consultas usando Python■ Função auxiliar para simplificar consultas
In : query_db('teste.db','SELECT * FROM Projects WHERE Prioridade="Baixa"') Out: [{'Concelho': 'Setubal', 'Custo': 100000.0, 'Nome': 'Arribas da praia de Galapos', 'Prioridade': 'Baixa'}] In : query_db('teste.db','SELECT * FROM Projects WHERE Prioridade="Elevada"') Out: [{'Concelho': 'Vila do Bispo', 'Custo': 2500000.0, 'Nome': 'Alimentacao artificial da praia da Mareta', 'Prioridade': 'Elevada'}, {'Concelho': 'Portimao', 'Custo': 30000.0, 'Nome': 'Saneamento da arriba na praia do Vau', 'Prioridade': 'Elevada'}]
-
27
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Função para obter projectos dada a prioridade■ Esta agora é fácil:
def with_priority(db_name,priority): "return dictionary with projects of given priority" query = 'SELECT * FROM Projects WHERE Prioridade = "{0}";' query = query.format(priority) return query_db(db_name,query)
In : with_priority('teste.db','Baixa') Out: [{'Concelho': 'Setubal', 'Custo': 100000.0, 'Nome': 'Arribas da praia de Galapos', 'Prioridade': 'Baixa'}]
-
28
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Função para organizar projectos por prioridade■ Devolve um dicionário com todas as prioridades na tabela■ Cada entrada desse dicionário tem a lista de dicionários com os
projectos correspondentes
def projects_by_priority(db_name): "return dictionary with priorities and all projects in list" projects = {} priorities = query_db(db_name,'SELECT DISTINCT Prioridade from Projects;') for entry in priorities: priority = entry['Prioridade'] projects[priority] = with_priority(db_name,priority) return projects
■ Usamos SELECT DISTINCT Prioridade para listar prioridades■ Para cada uma criamos a entrada no dicionário projects
-
29
ExemploExemploExemploExemploExemploExemploExemploExemploExemplo
Função para organizar projectos por prioridadeIn : projects = projects_by_priority('teste.db') In : projects.keys() Out: dict_keys(['Media', 'Baixa', 'Elevada']) In : projects['Elevada'] Out: [{'Concelho': 'Vila do Bispo', 'Custo': 2500000.0, 'Nome': 'Alimentacao artificial da praia da Mareta', 'Prioridade': 'Elevada'}, {'Concelho': 'Portimao', 'Custo': 30000.0, 'Nome': 'Saneamento da arriba na praia do Vau', 'Prioridade': 'Elevada'}] In : projects['Baixa'] Out: [{'Concelho': 'Setubal', 'Custo': 100000.0, 'Nome': 'Arribas da praia de Galapos', 'Prioridade': 'Baixa'}]
-
30
Sqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + PythonSqlite + Python
ResumoResumoResumoResumoResumoResumoResumoResumoResumo
-
31
ResumoResumoResumoResumoResumoResumoResumoResumoResumo
Sqlite e Python■ Python permite-nos processar os dados de muitas formas• Gráficos, ajuste de modelos, processar ficheiros, etc
■ Mas um SGBD permite gerir os dados de forma independente• Mais fácil de trocar informação com outros programas (e.g. sqliteman)• Optimizado para gerir dados (atomicidade, grande volume, etc)
■ Combinar os dois pode ser uma boa solução• Módulo sqlite3: ligar, criar cursor, executar e fechar
Leitura adicional:■ Recomendada: Capítulo 17 dos apontamentos■ Opcional: sqlite3: https://docs.python.org/3.6/library/sqlite3.html