Python - Aula 4 Bruno Gama Catão Bancos de Dados
DB-API • Python Database API Specification; • Módulos que integram Python a uma tecnologia de banco de dados devem implementar esta especificação; • Conceitos: • Conexão: Canal de comunicação entre o SGBD e a aplicação; • Cursor: Objeto responsável por enviar comandos ao banco de dados.
DB-API • Operações sobre conexões: • commit: persiste os dados de uma sessão no banco de dados; • rollback: descarta os valores da sessão; • Operações sobre cursores: • execute: executa um comando no banco de dados; • fetchall: retorna todos os valores produzidos pelo comando executado; • fetchone: retorna apenas um valor; • fechsome: retorna no máximo o número especificado de valores.
SQLITE • Já vem integrado com o Python a partir da versão 2.5; • Acessível através da biblioteca sqlite3; • Armazena os bancos de dados em arquivos; • Compatível com o padrão SQL92; • Suporta transações; • Suporta bancos de dados de até 2 TB.
SQLITE • Primeiro exemplo, Agenda (para variar ...); • Criando um banco de dados: • sqlite3 agenda.db agenda --------------------------- • Criando uma tabela: * id : INTEGER nome : VARCHAR(30) CREATE TABLE agenda ( tel : VARCHAR(20) id INTEGER PRIMARY KEY, nome VARCHAR(30), tel VARCHAR(20));
SQLITE • Inserindo dados: • INSERT INTO agenda(nome, tel) VALUES (‘Pedro’, ‘555-5555’); • INSERT INTO agenda(nome, tel) VALUES (‘Maria’, ‘333-3333’); • INSERT INTO agenda(nome, tel) VALUES (‘José’, ‘444-4444’); • INSERT INTO agenda(nome, tel) VALUES (‘Ana’, ‘666-6666’); • Para encerrar o SQLITE pressione CONTROL+D; • Verifique se o arquivo agenda.db foi criado.
Módulo SQLITE3 • Módulo compatível com a DB-API; • Utilizando o módulo: • from sqlite3 import dbapi2 as sqlite • Criando uma conexão: Atenção: O arquivo agenda.db • con = sqlite.connect('agenda.db') deve estar no diretório corrente, caso contrário especifique o caminho completo para o arquivo. • Obtendo um cursor: • cursor = con.cursor( )
Módulo SQLITE3 • Realizando uma consulta: • cursor.execute('select * from agenda') • Obtendo os valores da consulta: • dados = cursor.fetchall( ) • O método fetchall retorna uma lista com todos os dados da consulta; • Você pode preferir retornar um número menor de dados utilizando os métodos fetchone ou fetchsome.
Módulo SQLITE3 • Note que os dados retornados pelo fetchall são uma lista: • [(1, u'Escola Técnica Federal de Palmas', u'63-3225-1205'), (2, u'Aeroporto de Palmas', u'63-3219-3700'), (3, u'Água e Esgoto', u'0800-644-0195'), (4, u'Energia Elétrica', u'0800-646-4196'), (5, u'Disque-Denúncia', u'0800-63-1190'), (6, u'Polícia Civil', u'63-3218-5000'), (7, u'Prefeitura Municipal', u'63-3218-5000'), (8, u'Alcoólicos Anônimos', u'63-3215-4165')] • Você pode acessar esses valores pelo índice: • Nome do primeiro registro: dados[0][1] • Ou fazer algo com um jeito mais Python: cursor.execute('SELECT nome, tel FROM agenda ORDER BY nome') for nome, tel in cursor.fetchall(): print nome, tel
Módulo SQLITE3 • Para inserir, remover ou atualizar dados você deve utilizar uma transação; • Por exemplo: # -*- coding: latin-1 -*- from sqlite3 import dbapi2 as sqlite #Abrindo uma conexão con = sqlite.connect('agenda.db') #Obtendo um cursor cursor = con.cursor() cursor.execute("INSERT INTO agenda(nome, tel) VALUES('Bruno', '123')") #Salvando os dados da transação con.commit()
Módulo SQLITE3 • Passando parâmetros; • É importante prestar atenção a forma como os parâmetros são passados para evitar ataques de SQL Injection no seu sistema; • Forma errada: • cursor.execute('INSERT INTO agenda(nome,tel) VALUES (%s, %s)' % (nome, tel)) • Forma correta: • cursor.execute('INSERT INTO agenda(nome,tel) VALUES (?, ?)', (nome, tel))
Módulo SQLITE3 - O nome dele - Bem, nós perdemos o Oi, aqui é a escola realmente é Robert’); registro deste ano de - Nossa, ele DROP TABLE todos os estudantes. do seu filho. Nós quebrou algo ? Students;--? Espero que você esteja estamos tendo um - De certa forma - É sim. Nós o feliz. problema com sim. chamados de - E eu espero que você computadores. pequeno Bobby tenha aprendido a tratar Tables. os dados de entrada.
# -*- coding: latin-1 -*- Este é um from sqlite3 import dbapi2 as sqlite programa completo ! #Abrindo uma conexão con = sqlite.connect('agenda.db') #Obtendo um cursor cursor = con.cursor() while True: opcao = raw_input('Qual a sua opção (a)dicionar, (l)istar ou (s)air: ') if opcao == 'a': nome = raw_input('Digite o nome: ') tel = raw_input('Digite o telefone: ') cursor.execute('INSERT INTO agenda(nome,tel) VALUES (?, ?)', (nome, tel)) con.commit() elif opcao == 'l': cursor.execute('SELECT nome, tel FROM agenda ORDER BY nome') for nome, tel in cursor.fetchall(): print nome, tel elif opcao == 's': break else: print 'Digite uma opção válida !'
SQLAlchemy • É uma biblioteca que facilita a utilização de bancos de dados por aplicações Python; • O SQLAlchemy faz o mapeamento objecto-relacional entre os objetos Python a as tabelas de um banco de dados; • SQLAlchemy é suporta qualquer banco de dados que possua módulo DB- API; • A instalação do SQLAlchemy pode ser feita de duas formas: • Fazendo o download; http://www.sqlalchemy.org/ • Utilizando o setuptools.
Setup Tools • Objetivo: Instalação fácil de pacotes Python; • Link para download: • http://pypi.python.org/pypi/setuptools/ • Instalação: • Windows: • Execute o arquivo setuptools-0.6c11.win32-py2.6.exe; • Linux e MacOS: • sudo sh setuptools-0.6c11-py2.6.egg
SQLAlchemy • Instalação: • Windows: • easy_install SQLAlchemy • Linux e MacOS: • sudo easy_install SQLAlchemy
SQLAlchemy • Conceitos básicos: • Você deve criar classes para mapear as tabelas do banco de dados; • As operações serão feitas apenas sobre as classes, não necessitando trabalhar com SQL; • A conexão ao banco de dados é feita através de uma engine; • As operações com o banco de dados são feitas em uma sessão; • Uma sessão define uma transação.
SQLAlchemy • Mapeando uma classe em uma tabela: • É necessário criar uma classe para cada tabela que se queira mapear; • As próprias classes podem ser utilizadas para criar as tabelas, caso elas não existam; • Forma geral: from sqlalchemy import * from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Contato(Base): __tablename__ = 'agenda' Atributo obrigatório id = Column(Integer, primary_key=True) nome = Column(String) tel = Column(String)
SQLAlchemy • Toda classe mapeada é subclasse de declarative_base; • No SQLAlchemy toda tabela/classe mapeada deve ter uma chave primária; • Não é necessário criar um construtor para as classes mapeadas; • Todas as colunas tem um tipo associado (Integer, String, Numeric, etc); • Se você está utilizando o PostgreSQL ou o SQLite são há necessidade de especificar o tamanho das colunas, mas para os outros bancos é obrigatório indicar este tamanho: class Contato(Base): __tablename__ = 'agenda' id = Column(Integer, primary_key=True) nome = Column(String(30)) tel = Column(String(20))
SQLAlchemy • Com exceção do Oracle e do Firebird, todos os outros bancos de dados têm suporte a colunas com auto incremento (para as chaves primárias); • Para o Oracle e Firebird é necessário especificar uma seqüência: class Contato(Base): __tablename__ = 'agenda' id = Column(Integer, Sequence('contato_seq'), primary_key=True) nome = Column(String(30)) tel = Column(String(20))
SQLAlchemy Nome do SGBD • Obtendo uma engine: • engine = create_engine('sqlite:///agenda.db') URL para o banco de dados • O nome do SGBD é uma forma do SQLAlchemy localizar o módulo correto, alguns exemplos de nomes são: sqlite, mysql, postgresql, mssql, oracle, ... • A URL para o banco de dados é dependente do módulo que se está utilizando, por isso, deve-se ler a documentação do módulo para saber como construir a URL; • Exemplos: mssql://user:passwd@mydsn, oracle://scott:tiger@127.0.0.1:1521/ sidname, mysql://scott:tiger@localhost/foo, ... • Você pode, na criação, pedir que a engine mostre todos o código SQL gerado por ela: create_engine('sqlite:///agenda.db', echo=True)
SQLAlchemy • Criando automaticamente as tabelas: • Para isto, após a definição do mapeamento, utiliza-se o atributo metadata da classe Base: Base.metadata.create_all(engine) • Obtendo uma sessão: • As sessões estão sempre associadas a uma engine: Session = sessionmaker(bind=engine) session = Session()
SQLAlchemy • Gravando objetos no banco de dados: • session.add(objeto) • session.commit( ) • Você pode adicionar uma lista de objetos de uma vez só: • session.add_all([objeto1, objeto2, objeto3]) • Atenção: Lembre-se sempre de após um bloco de atualizações realizar o commit, pois, caso contrário, os dados não serão persistidos; • Caso algum erro ocorra, você deve chamar o rollback, para deixar o estado do banco de dados igual ao do último commit realizado.
SQLAlchemy - Consultas • Pela chave primária: • bruno = session.query(Contato).get(5) • Retornando todos os registros: • contatos = session.query(Contato).all( ) • Ordenando os resultados: • contatos = session.query(Contato).order_by(Contato.nome).all( ) • Filtrando por um campo: • pedro = session.query(Contato).filter(nome=”Pedro”).first( ) • Restringindo os resultados: • Você pode usar o método all, para obter todos os resultados ou first para obter apenas o primeiro.
SQLAlchemy • Para alterar um registro é preciso: obtê-lo na sessão, modificar seus valores e fazer commit da sessão: contato = session.query(Contato).get(5) contato.tel = '8888-8888' session.commit() • Para remover um registro é preciso: obtê-lo, chamar o método delete na sessão e fazer commit: contato = session.query(Contato).get(5) session.delete(contato) session.commit()
SQLAlchemy • Vamos reproduzir o nosso exemplo anterior criando um novo projeto do PyDev chamado Agenda; • Este projeto será composto por dois módulos contato.py e principal.py; • O módulo contato.py irá conter o mapeamento da classe Contato com a tabela agenda; • O módulo principal.py terá o código do programa principal.
SQLAlchemy - Módulo contato.py from sqlalchemy import * from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Contato(Base): __tablename__ = 'agenda' id = Column(Integer, primary_key=True) nome = Column(String) tel = Column(String) def __init__(self, nome, tel): self.nome = nome self.tel = tel
SQLAlchemy - Módulo principal.py • Apenas o cabeçalho e os imports: # -*- coding: latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from contato import Contato, Base import os • Continua ...
engine = create_engine('sqlite:///agenda.db') Session = sessionmaker(bind=engine) session = Session() if not os.path.exists('agenda.db'): Base.metadata.create_all(engine) while True: opcao = raw_input('Qual a sua opção (a)dicionar, (l)istar ou (s)air: ') if opcao == 'a': nome = raw_input('Digite o nome: ') tel = raw_input('Digite o telefone: ') session.add(Contato(nome, tel)) session.commit() elif opcao == 'l': for contato in session.query(Contato).order_by(Contato.nome): print contato.nome, contato.tel elif opcao == 's': break else: print 'Digite uma opção válida !'

Python 04

  • 1.
    Python - Aula4 Bruno Gama Catão Bancos de Dados
  • 2.
    DB-API • Python DatabaseAPI Specification; • Módulos que integram Python a uma tecnologia de banco de dados devem implementar esta especificação; • Conceitos: • Conexão: Canal de comunicação entre o SGBD e a aplicação; • Cursor: Objeto responsável por enviar comandos ao banco de dados.
  • 3.
    DB-API • Operações sobreconexões: • commit: persiste os dados de uma sessão no banco de dados; • rollback: descarta os valores da sessão; • Operações sobre cursores: • execute: executa um comando no banco de dados; • fetchall: retorna todos os valores produzidos pelo comando executado; • fetchone: retorna apenas um valor; • fechsome: retorna no máximo o número especificado de valores.
  • 4.
    SQLITE • Já vemintegrado com o Python a partir da versão 2.5; • Acessível através da biblioteca sqlite3; • Armazena os bancos de dados em arquivos; • Compatível com o padrão SQL92; • Suporta transações; • Suporta bancos de dados de até 2 TB.
  • 5.
    SQLITE • Primeiro exemplo,Agenda (para variar ...); • Criando um banco de dados: • sqlite3 agenda.db agenda --------------------------- • Criando uma tabela: * id : INTEGER nome : VARCHAR(30) CREATE TABLE agenda ( tel : VARCHAR(20) id INTEGER PRIMARY KEY, nome VARCHAR(30), tel VARCHAR(20));
  • 6.
    SQLITE • Inserindo dados: • INSERT INTO agenda(nome, tel) VALUES (‘Pedro’, ‘555-5555’); • INSERT INTO agenda(nome, tel) VALUES (‘Maria’, ‘333-3333’); • INSERT INTO agenda(nome, tel) VALUES (‘José’, ‘444-4444’); • INSERT INTO agenda(nome, tel) VALUES (‘Ana’, ‘666-6666’); • Para encerrar o SQLITE pressione CONTROL+D; • Verifique se o arquivo agenda.db foi criado.
  • 7.
    Módulo SQLITE3 • Módulocompatível com a DB-API; • Utilizando o módulo: • from sqlite3 import dbapi2 as sqlite • Criando uma conexão: Atenção: O arquivo agenda.db • con = sqlite.connect('agenda.db') deve estar no diretório corrente, caso contrário especifique o caminho completo para o arquivo. • Obtendo um cursor: • cursor = con.cursor( )
  • 8.
    Módulo SQLITE3 • Realizandouma consulta: • cursor.execute('select * from agenda') • Obtendo os valores da consulta: • dados = cursor.fetchall( ) • O método fetchall retorna uma lista com todos os dados da consulta; • Você pode preferir retornar um número menor de dados utilizando os métodos fetchone ou fetchsome.
  • 9.
    Módulo SQLITE3 • Noteque os dados retornados pelo fetchall são uma lista: • [(1, u'Escola Técnica Federal de Palmas', u'63-3225-1205'), (2, u'Aeroporto de Palmas', u'63-3219-3700'), (3, u'Água e Esgoto', u'0800-644-0195'), (4, u'Energia Elétrica', u'0800-646-4196'), (5, u'Disque-Denúncia', u'0800-63-1190'), (6, u'Polícia Civil', u'63-3218-5000'), (7, u'Prefeitura Municipal', u'63-3218-5000'), (8, u'Alcoólicos Anônimos', u'63-3215-4165')] • Você pode acessar esses valores pelo índice: • Nome do primeiro registro: dados[0][1] • Ou fazer algo com um jeito mais Python: cursor.execute('SELECT nome, tel FROM agenda ORDER BY nome') for nome, tel in cursor.fetchall(): print nome, tel
  • 10.
    Módulo SQLITE3 • Para inserir, remover ou atualizar dados você deve utilizar uma transação; • Por exemplo: # -*- coding: latin-1 -*- from sqlite3 import dbapi2 as sqlite #Abrindo uma conexão con = sqlite.connect('agenda.db') #Obtendo um cursor cursor = con.cursor() cursor.execute("INSERT INTO agenda(nome, tel) VALUES('Bruno', '123')") #Salvando os dados da transação con.commit()
  • 11.
    Módulo SQLITE3 • Passandoparâmetros; • É importante prestar atenção a forma como os parâmetros são passados para evitar ataques de SQL Injection no seu sistema; • Forma errada: • cursor.execute('INSERT INTO agenda(nome,tel) VALUES (%s, %s)' % (nome, tel)) • Forma correta: • cursor.execute('INSERT INTO agenda(nome,tel) VALUES (?, ?)', (nome, tel))
  • 12.
    Módulo SQLITE3 - O nome dele - Bem, nós perdemos o Oi, aqui é a escola realmente é Robert’); registro deste ano de - Nossa, ele DROP TABLE todos os estudantes. do seu filho. Nós quebrou algo ? Students;--? Espero que você esteja estamos tendo um - De certa forma - É sim. Nós o feliz. problema com sim. chamados de - E eu espero que você computadores. pequeno Bobby tenha aprendido a tratar Tables. os dados de entrada.
  • 13.
    # -*- coding:latin-1 -*- Este é um from sqlite3 import dbapi2 as sqlite programa completo ! #Abrindo uma conexão con = sqlite.connect('agenda.db') #Obtendo um cursor cursor = con.cursor() while True: opcao = raw_input('Qual a sua opção (a)dicionar, (l)istar ou (s)air: ') if opcao == 'a': nome = raw_input('Digite o nome: ') tel = raw_input('Digite o telefone: ') cursor.execute('INSERT INTO agenda(nome,tel) VALUES (?, ?)', (nome, tel)) con.commit() elif opcao == 'l': cursor.execute('SELECT nome, tel FROM agenda ORDER BY nome') for nome, tel in cursor.fetchall(): print nome, tel elif opcao == 's': break else: print 'Digite uma opção válida !'
  • 14.
    SQLAlchemy • É umabiblioteca que facilita a utilização de bancos de dados por aplicações Python; • O SQLAlchemy faz o mapeamento objecto-relacional entre os objetos Python a as tabelas de um banco de dados; • SQLAlchemy é suporta qualquer banco de dados que possua módulo DB- API; • A instalação do SQLAlchemy pode ser feita de duas formas: • Fazendo o download; http://www.sqlalchemy.org/ • Utilizando o setuptools.
  • 15.
    Setup Tools • Objetivo:Instalação fácil de pacotes Python; • Link para download: • http://pypi.python.org/pypi/setuptools/ • Instalação: • Windows: • Execute o arquivo setuptools-0.6c11.win32-py2.6.exe; • Linux e MacOS: • sudo sh setuptools-0.6c11-py2.6.egg
  • 16.
    SQLAlchemy • Instalação: • Windows: • easy_install SQLAlchemy • Linux e MacOS: • sudo easy_install SQLAlchemy
  • 17.
    SQLAlchemy • Conceitos básicos: • Você deve criar classes para mapear as tabelas do banco de dados; • As operações serão feitas apenas sobre as classes, não necessitando trabalhar com SQL; • A conexão ao banco de dados é feita através de uma engine; • As operações com o banco de dados são feitas em uma sessão; • Uma sessão define uma transação.
  • 18.
    SQLAlchemy • Mapeando umaclasse em uma tabela: • É necessário criar uma classe para cada tabela que se queira mapear; • As próprias classes podem ser utilizadas para criar as tabelas, caso elas não existam; • Forma geral: from sqlalchemy import * from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Contato(Base): __tablename__ = 'agenda' Atributo obrigatório id = Column(Integer, primary_key=True) nome = Column(String) tel = Column(String)
  • 19.
    SQLAlchemy • Toda classemapeada é subclasse de declarative_base; • No SQLAlchemy toda tabela/classe mapeada deve ter uma chave primária; • Não é necessário criar um construtor para as classes mapeadas; • Todas as colunas tem um tipo associado (Integer, String, Numeric, etc); • Se você está utilizando o PostgreSQL ou o SQLite são há necessidade de especificar o tamanho das colunas, mas para os outros bancos é obrigatório indicar este tamanho: class Contato(Base): __tablename__ = 'agenda' id = Column(Integer, primary_key=True) nome = Column(String(30)) tel = Column(String(20))
  • 20.
    SQLAlchemy • Com exceçãodo Oracle e do Firebird, todos os outros bancos de dados têm suporte a colunas com auto incremento (para as chaves primárias); • Para o Oracle e Firebird é necessário especificar uma seqüência: class Contato(Base): __tablename__ = 'agenda' id = Column(Integer, Sequence('contato_seq'), primary_key=True) nome = Column(String(30)) tel = Column(String(20))
  • 21.
    SQLAlchemy Nome do SGBD • Obtendo uma engine: • engine = create_engine('sqlite:///agenda.db') URL para o banco de dados • O nome do SGBD é uma forma do SQLAlchemy localizar o módulo correto, alguns exemplos de nomes são: sqlite, mysql, postgresql, mssql, oracle, ... • A URL para o banco de dados é dependente do módulo que se está utilizando, por isso, deve-se ler a documentação do módulo para saber como construir a URL; • Exemplos: mssql://user:passwd@mydsn, oracle://scott:tiger@127.0.0.1:1521/ sidname, mysql://scott:tiger@localhost/foo, ... • Você pode, na criação, pedir que a engine mostre todos o código SQL gerado por ela: create_engine('sqlite:///agenda.db', echo=True)
  • 22.
    SQLAlchemy • Criando automaticamenteas tabelas: • Para isto, após a definição do mapeamento, utiliza-se o atributo metadata da classe Base: Base.metadata.create_all(engine) • Obtendo uma sessão: • As sessões estão sempre associadas a uma engine: Session = sessionmaker(bind=engine) session = Session()
  • 23.
    SQLAlchemy • Gravando objetosno banco de dados: • session.add(objeto) • session.commit( ) • Você pode adicionar uma lista de objetos de uma vez só: • session.add_all([objeto1, objeto2, objeto3]) • Atenção: Lembre-se sempre de após um bloco de atualizações realizar o commit, pois, caso contrário, os dados não serão persistidos; • Caso algum erro ocorra, você deve chamar o rollback, para deixar o estado do banco de dados igual ao do último commit realizado.
  • 24.
    SQLAlchemy - Consultas •Pela chave primária: • bruno = session.query(Contato).get(5) • Retornando todos os registros: • contatos = session.query(Contato).all( ) • Ordenando os resultados: • contatos = session.query(Contato).order_by(Contato.nome).all( ) • Filtrando por um campo: • pedro = session.query(Contato).filter(nome=”Pedro”).first( ) • Restringindo os resultados: • Você pode usar o método all, para obter todos os resultados ou first para obter apenas o primeiro.
  • 25.
    SQLAlchemy • Para alterarum registro é preciso: obtê-lo na sessão, modificar seus valores e fazer commit da sessão: contato = session.query(Contato).get(5) contato.tel = '8888-8888' session.commit() • Para remover um registro é preciso: obtê-lo, chamar o método delete na sessão e fazer commit: contato = session.query(Contato).get(5) session.delete(contato) session.commit()
  • 26.
    SQLAlchemy • Vamos reproduziro nosso exemplo anterior criando um novo projeto do PyDev chamado Agenda; • Este projeto será composto por dois módulos contato.py e principal.py; • O módulo contato.py irá conter o mapeamento da classe Contato com a tabela agenda; • O módulo principal.py terá o código do programa principal.
  • 27.
    SQLAlchemy - Módulocontato.py from sqlalchemy import * from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class Contato(Base): __tablename__ = 'agenda' id = Column(Integer, primary_key=True) nome = Column(String) tel = Column(String) def __init__(self, nome, tel): self.nome = nome self.tel = tel
  • 28.
    SQLAlchemy - Móduloprincipal.py • Apenas o cabeçalho e os imports: # -*- coding: latin-1 -*- from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from contato import Contato, Base import os • Continua ...
  • 29.
    engine = create_engine('sqlite:///agenda.db') Session= sessionmaker(bind=engine) session = Session() if not os.path.exists('agenda.db'): Base.metadata.create_all(engine) while True: opcao = raw_input('Qual a sua opção (a)dicionar, (l)istar ou (s)air: ') if opcao == 'a': nome = raw_input('Digite o nome: ') tel = raw_input('Digite o telefone: ') session.add(Contato(nome, tel)) session.commit() elif opcao == 'l': for contato in session.query(Contato).order_by(Contato.nome): print contato.nome, contato.tel elif opcao == 's': break else: print 'Digite uma opção válida !'