Fork me on GitHub

Problema com primary key datetime.

Trabalhei em uma tarefa que possuía uma tabela legada que tinha como uma chave primária composta sendo um campo de string e o outro datetime.

from sqlalchemy import Column, String, DateTime
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class BlogExemplo(Base):
    __tablename__ = 'blog_exemplo'
    campo_um = Column(String, primary_key=True)
    campo_dois = Column(DateTime, primary_key=True)
    campo_tres = Column(String)

Até esse momento nenhum problema. Possuímos um débito técnico no nosso servidor que a hora do máquina não é a mesma do banco de dados. Com isso, SEMPRE precisamos utilizar a função do banco de dados sysdate para obter a data do banco para depois atribui a uma coluna.

Nesse momento, no primeiro teste que fiz para criar um novo registro no banco de dados. Criei um instance da classe como segue o exemplo e tentei salvar no banco de dados.

exemplo = BlogExemplo()
exemplo.campo_um = "texto_1"
exemplo.campo_dois = func.sysdate()
exemplo.campo_tres = "outro texto"
db.add(exemplo)
db.commit()

A minha expectativa era que salvasse no banco de dados e que eu proseguiria com meu desenvolvimento, mas o que aconteceu foi um erro ser lançado com a informação que eu não tinha dados no chave primária campo_dois.

Investiguei e percebi que o ORM faz uma checagem antes de valores e como o func.sysdate() somente é executado no DB, asim para o ORM eu não tinha adicionado um valor para o campo.

Para resolver meu problema, eu segui a estratégia de criar uma função para obter data/hora e atribuir para a variável.

from sqlalchemy.sql import text


def obter_hora_servidor():
    stmt = text("SELECT sysdate from DUAL;")
    result = conn.execute(stmt)
    return result.scalar()


exemplo = BlogExemplo()
exemplo.campo_um = "texto_1"
exemplo.campo_dois = obter_hora_servidor()
exemplo.campo_tres = "outro texto"
db.add(exemplo)
db.commit()

Assim conseguir resolver meu problema.

Obs: Esse problema somente acontecia na hora de criar um novo objeto. Se fosse para atualizar um existente poderia utilizar a func.sysdate().

social