Inserindo um objeto Python datetime.datetime no MySQL

120

Eu tenho uma coluna de data em uma tabela MySQL. Quero inserir um datetime.datetime()objeto nesta coluna. O que devo usar na instrução execute?

Eu tentei:

now = datetime.datetime(2009,5,5)

cursor.execute("INSERT INTO table
(name, id, datecolumn) VALUES (%s, %s
, %s)",("name", 4,now))

Estou recebendo uma mensagem de erro como: "TypeError: not all arguments converted during string formatting" O que devo usar em vez de %s?

Peter Mortensen
fonte
você perdeu cotações%s cursor.execute("INSERT INTO table (name, id, datecolumn) VALUES (%s, %s , '%s')",("name", 4,now))
Sheshnath

Respostas:

198

Para um campo de hora, use:

import time    
time.strftime('%Y-%m-%d %H:%M:%S')

Acho que strftime também se aplica a datetime.

g33kz0r
fonte
4
Além disso, certifique-se de que o nome da coluna não seja uma palavra reservada . Levei 30 minutos para perceber que o nome "data_atual" estava causando problemas ... ugh!
Pakman
2
O que está timeneste exemplo?
James McMahon de
1
J McMahon: o tempo é um módulo Python.
dstromberg 01 de
E se alguém quiser buscar o único ano, mês, dia?
Pooja Khatri
42

Provavelmente, você está recebendo o TypeError porque precisa de aspas em torno do valor da coluna de dados.

Experimentar:

now = datetime.datetime(2009, 5, 5)

cursor.execute("INSERT INTO table (name, id, datecolumn) VALUES (%s, %s, '%s')",
               ("name", 4, now))

Com relação ao formato, tive sucesso com o comando acima (que inclui os milissegundos) e com:

now.strftime('%Y-%m-%d %H:%M:%S')

Espero que isto ajude.

Edvinas
fonte
8
Você pode não ter aspas %sem torno de pymsql.
Martin Thoma
1
As citações em torno do terceiro% s causam erros quando tento fazer isso.
realjin
13

Tente usar now.date()para obter um Dateobjeto em vez de um DateTime.

Se isso não funcionar, convertê-lo em uma string deve funcionar:

now = datetime.datetime(2009,5,5)
str_now = now.date().isoformat()
cursor.execute('INSERT INTO table (name, id, datecolumn) VALUES (%s,%s,%s)', ('name',4,str_now))
Wogan
fonte
Você não precisa adicionar aspas em torno dos parâmetros da string, por exemplo, "... VALUES ('% s', '% s', '% s')"
Gareth Simpson
5

Use o método Python datetime.strftime(format), onde format = '%Y-%m-%d %H:%M:%S'.

import datetime

now = datetime.datetime.utcnow()

cursor.execute("INSERT INTO table (name, id, datecolumn) VALUES (%s, %s, %s)",
               ("name", 4, now.strftime('%Y-%m-%d %H:%M:%S')))

Fusos horários

Se os fusos horários forem uma preocupação, o fuso horário do MySQL pode ser definido para UTC da seguinte maneira:

cursor.execute("SET time_zone = '+00:00'")

E o fuso horário pode ser definido em Python:

now = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)

Documentação MySQL

O MySQL reconhece os valores DATETIME e TIMESTAMP nestes formatos:

Como uma string no formato 'AAAA-MM-DD HH: MM: SS' ou 'AA-MM-DD HH: MM: SS' . Uma sintaxe “relaxada” também é permitida aqui: qualquer caractere de pontuação pode ser usado como delimitador entre as partes da data ou hora. Por exemplo, '2012-12-31 11:30:45', '2012 ^ 12 ^ 31 11 + 30 + 45', '2012/12/31 11 * 30 * 45' e '2012 @ 12 @ 31 11 ^ 30 ^ 45 'são equivalentes.

O único delimitador reconhecido entre uma parte de data e hora e uma parte de segundos fracionários é o ponto decimal.

As partes de data e hora podem ser separadas por T em vez de um espaço. Por exemplo, '2012-12-31 11:30:45' '2012-12-31T11: 30: 45' são equivalentes.

Como uma string sem delimitadores no formato 'AAAAMMDDHHMMSS' ou 'YYMMDDHHMMSS', desde que a string faça sentido como uma data. Por exemplo, '20070523091528' e '070523091528' são interpretados como '2007-05-23 09:15:28', mas '071122129015' é ilegal (tem uma parte de minuto sem sentido) e se torna '0000-00-00 00: 00:00 '.

Como um número no formato AAAAMMDDHHMMSS ou AAMMDDHHMMSS, desde que o número faça sentido como data. Por exemplo, 19830905132800 e 830905132800 são interpretados como '1983-09-05 13:28:00'.

Christopher Peisert
fonte
3

A qual banco de dados você está se conectando? Eu sei que a Oracle pode ser exigente quanto aos formatos de data e gosta do formato ISO 8601 .

** Nota: Oops, acabei de ler que você está no MySQL. Basta formatar a data e tentar como uma chamada SQL direta separada para teste.

Em Python, você pode obter uma data ISO como

now.isoformat()

Por exemplo, a Oracle gosta de datas como

insert into x values(99, '31-may-09');

Dependendo do seu banco de dados, se for Oracle, pode ser necessário TO_DATE:

insert into x
values(99, to_date('2009/05/31:12:00:00AM', 'yyyy/mm/dd:hh:mi:ssam'));

O uso geral de TO_DATE é:

TO_DATE(<string>, '<format>')

Se estiver usando outro banco de dados (vi o cursor e pensei Oracle; posso estar errado) verifique suas ferramentas de formato de data. Para MySQL é DATE_FORMAT () e SQL Server é CONVERT.

Usar também uma ferramenta como o SQLAlchemy removerá diferenças como essas e facilitará sua vida.

Ryan Christensen
fonte
Eu não recomendo usar datetime.isoformat () porque se você usar um objeto ciente de fuso horário, a string gerada inclui dados de fuso horário e não corresponde mais ao formato mysql necessário.
Frankster
0

Se você estiver usando apenas um datetime.date python (não um datetime.datetime completo), apenas converta a data como uma string. Isso é muito simples e funciona para mim (mysql, python 2.7, Ubuntu). A coluna published_dateé um campo de data do MySQL, a variável python publish_dateé datetime.date.

# make the record for the passed link info
sql_stmt = "INSERT INTO snippet_links (" + \
    "link_headline, link_url, published_date, author, source, coco_id, link_id)" + \
    "VALUES(%s, %s, %s, %s, %s, %s, %s) ;"

sql_data = ( title, link, str(publish_date), \
             author, posted_by, \
             str(coco_id), str(link_id) )

try:
    dbc.execute(sql_stmt, sql_data )
except Exception, e:
    ...
jbartas
fonte
0

quando está inserindo em t-sql

isso falha:

select CONVERT(datetime,'2019-09-13 09:04:35.823312',21)

isso funciona:

select CONVERT(datetime,'2019-09-13 09:04:35.823',21)

jeito fácil:

regexp = re.compile(r'\.(\d{6})')
def to_splunk_iso(dt):
    """Converts the datetime object to Splunk isoformat string."""
    # 6-digits string.
    microseconds = regexp.search(dt).group(1)
    return regexp.sub('.%d' % round(float(microseconds) / 1000), dt)
Krzysztof Drewicz
fonte