-
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