Recentemente eu comecei a desenvolver um sistema em Python. Para os que não são da área de TI, basta saber que é uma linguagem de programação. Para os que são da área de TI: gente, Python obriga o desenvolvedor a identar o código! Dá erro se não identar! Só por causa disso eu já queria adicionar o Guido van Rossum no Facebook, mas ainda por cima o site é bonito, organizado e amigável e a documentação é completa e fácil de consultar.
Na verdade, me ocorre agora que o povo que não é de TI não vai ter o menor interesse neste post. Então, segue a imagem de um coelhinho pra vocês não perderem a viagem.
Voltando ao assunto, até agora estou conseguindo usar só o que já vem na instalação padrão do Python, inclusive o IDLE, que é uma IDE bem pobrezinha, mas meio que já me habituei com ele e com suas limitações e estamos nos entendendo bem. Como a minha aplicação é monousuário e os únicos usuários são meu irmão e minha cunhada, optei por um banco de dados embarcado: o sqlite3 também já vem na instalação padrão do Python, o que torna tudo mais simples.
Quer dizer, simples desde que você não precise definir uma chave estrangeira. Sabe chave estrangeira, aquela coisa que todo banco de dados relacional tem para atender à primeira forma normal? Pois é: você pode até defini-las no seu banco, mas não faz a menor diferença e você continua conseguindo excluir o registro na tabela principal, deixando pra trás aquele monte de registros órfãos com uma chave estrangeira que aponta pra lugar nenhum.
Amei o Python um pouquinho menos no dia em que descobri isso. Tudo bem que o problema não é exatamente o Python, e sim o SQLite, mas, quando você inclui algo na instalação padrão, eu encaro isso como um endosso.
Depois de me recuperar do choque de ver minha chave estrangeira ser solenemente ignorada, fui pesquisar o que estava acontecendo e vi que a solução é até bastante simples, porque a constraint da chave estrangeira funciona, sim, e está só desabilitada. E é muito fácil de habilitar, e está explicado bem direitinho na documentação do SQLite. Mas quem desabilita por padrão as constraints de chave estrangeira, meu Deus? Certo, é uma questão de compatibilidade com versões anteriores, mas isso só levanta mais questionamentos: o que diabos estava acontecendo nessas versões mais antigas para que essa compatibilidade se fizesse necessária? E, independente disso: como é que não tem um aviso sobre isso em letras vermelhas garrafais pulando na cara do desenvolvedor no momento em que ele termina a instalação? Não acredito que algum desenvolvedor no mundo começa a usar um banco relacional e pensa "hum, vou conferir na documentação se as constraints de chave estrangeira funcionam mesmo, por via das dúvidas". Se tem alguém que faz isso, me diz onde você está que eu vou aí te dar um abraço, porque você deve ter passado por muitas experiências terríveis para ter ficado assim tão desconfiado de tudo e de todos.
Enfim, fica aqui registrada a solução: ao preparar a conexão com o banco, é só acrescentar uma linha habilitando as chaves estrangeiras.
Na verdade, me ocorre agora que o povo que não é de TI não vai ter o menor interesse neste post. Então, segue a imagem de um coelhinho pra vocês não perderem a viagem.
Uma imagem de um coelhinho pro povo que não é de TI não ficar aborrecido por ter vindo aqui à toa. (Image courtesy of Katriona Galahad at StockVault.net) |
Voltando ao assunto, até agora estou conseguindo usar só o que já vem na instalação padrão do Python, inclusive o IDLE, que é uma IDE bem pobrezinha, mas meio que já me habituei com ele e com suas limitações e estamos nos entendendo bem. Como a minha aplicação é monousuário e os únicos usuários são meu irmão e minha cunhada, optei por um banco de dados embarcado: o sqlite3 também já vem na instalação padrão do Python, o que torna tudo mais simples.
Quer dizer, simples desde que você não precise definir uma chave estrangeira. Sabe chave estrangeira, aquela coisa que todo banco de dados relacional tem para atender à primeira forma normal? Pois é: você pode até defini-las no seu banco, mas não faz a menor diferença e você continua conseguindo excluir o registro na tabela principal, deixando pra trás aquele monte de registros órfãos com uma chave estrangeira que aponta pra lugar nenhum.
Amei o Python um pouquinho menos no dia em que descobri isso. Tudo bem que o problema não é exatamente o Python, e sim o SQLite, mas, quando você inclui algo na instalação padrão, eu encaro isso como um endosso.
Depois de me recuperar do choque de ver minha chave estrangeira ser solenemente ignorada, fui pesquisar o que estava acontecendo e vi que a solução é até bastante simples, porque a constraint da chave estrangeira funciona, sim, e está só desabilitada. E é muito fácil de habilitar, e está explicado bem direitinho na documentação do SQLite. Mas quem desabilita por padrão as constraints de chave estrangeira, meu Deus? Certo, é uma questão de compatibilidade com versões anteriores, mas isso só levanta mais questionamentos: o que diabos estava acontecendo nessas versões mais antigas para que essa compatibilidade se fizesse necessária? E, independente disso: como é que não tem um aviso sobre isso em letras vermelhas garrafais pulando na cara do desenvolvedor no momento em que ele termina a instalação? Não acredito que algum desenvolvedor no mundo começa a usar um banco relacional e pensa "hum, vou conferir na documentação se as constraints de chave estrangeira funcionam mesmo, por via das dúvidas". Se tem alguém que faz isso, me diz onde você está que eu vou aí te dar um abraço, porque você deve ter passado por muitas experiências terríveis para ter ficado assim tão desconfiado de tudo e de todos.
Enfim, fica aqui registrada a solução: ao preparar a conexão com o banco, é só acrescentar uma linha habilitando as chaves estrangeiras.
# Fazer a conexão com o banco
conBD=sqlite3.connect("Dados\cp2.db")
conBD=sqlite3.connect("Dados\cp2.db")
# Criar as tabelas (se ainda não existirem)
conBD.execute("create table if not exists FABRICANTE FA_CD_FABRICANTE integer primary key, FA_NM_FABRICANTE varchar(30) unique not null, FA_TX_SITE varchar(30))")
conBD.execute("create table if not exists REVISTA (RE_CD_REVISTA integer primary key, FA_CD_FABRICANTE integer, RE_NM_REVISTA varchar(30) not null, unique (FA_CD_FABRICANTE, RE_NM_REVISTA), foreign key(FA_CD_FABRICANTE) references FABRICANTE(FA_CD_FABRICANTE))")
# Habilitar as chaves estrangeiras!
conBD.execute("PRAGMA foreign_keys = ON")
De acordo com a documentação, é possível que em versões futuras as chaves estrangeiras passem a vir habilitadas por padrão, mas, pelo menos até a versão 3.6.19, o caminho é esse.
P.S. Guido, não se preocupe: já está tudo perdoado e esquecido, viu? Me liga pra gente marcar aquele chope.
P.S. Guido, não se preocupe: já está tudo perdoado e esquecido, viu? Me liga pra gente marcar aquele chope.
Python parece mesmo ser uma linguagem interessante, ainda não cheguei a experimentá-la seguindo o manual, mas, pelo que pude observar até agora, ela é bastante utilizada em problemas de cunho científico.
ResponderExcluir