Inserimento di un oggetto datetime.datetime di Python in MySQL


120

Ho una colonna della data in una tabella MySQL. Voglio inserire un datetime.datetime()oggetto in questa colonna. Cosa dovrei usare nell'istruzione execute?

Ho provato:

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

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

Ricevo un errore del tipo: "TypeError: not all arguments converted during string formatting" cosa dovrei usare invece di %s?


ti sei perso le citazioni in giro%s cursor.execute("INSERT INTO table (name, id, datecolumn) VALUES (%s, %s , '%s')",("name", 4,now))
Sheshnath

Risposte:


198

Per un campo ora, utilizza:

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

Penso che strftime si applichi anche a datetime.


4
Inoltre, assicurati che il nome della tua colonna non sia una parola riservata . Mi ci sono voluti 30 minuti per capire che il nome "current_date" stava causando problemi ... ugh!
Pakman

2
Cosa c'è timein questo esempio?
James McMahon

1
J McMahon: il tempo è un modulo Python.
dstromberg

E se qualcuno volesse recuperare l'unico anno, mese, giorno?
Pooja Khatri

42

Molto probabilmente stai ottenendo TypeError perché hai bisogno di virgolette attorno al valore datecolumn.

Provare:

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

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

Per quanto riguarda il formato, ho avuto successo con il comando precedente (che include i millisecondi) e con:

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

Spero che questo ti aiuti.


8
Non si può avere le virgolette intorno %sa pymsql.
Martin Thoma

1
Le citazioni intorno al terzo% s causano errori quando provo questo.
realjin

13

Prova a usare now.date()per ottenere un Dateoggetto piuttosto che un file DateTime.

Se ciò non funziona, la conversione in una stringa dovrebbe funzionare:

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))

Non è necessario aggiungere virgolette intorno ai parametri della stringa, ad esempio "... VALUES ('% s', '% s', '% s')"
Gareth Simpson

5

Usa il metodo Python datetime.strftime(format), dove 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')))

Fusi orari

Se i fusi orari sono un problema, il fuso orario di MySQL può essere impostato per UTC come segue:

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

E il fuso orario può essere impostato in Python:

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

Documentazione MySQL

MySQL riconosce i valori DATETIME e TIMESTAMP in questi formati:

Come stringa in formato "AAAA-MM-GG HH: MM: SS" o "AA-MM-GG HH: MM: SS" . Anche qui è consentita una sintassi "rilassata": qualsiasi carattere di punteggiatura può essere utilizzato come delimitatore tra parti di data o parti di tempo. Ad esempio, "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 'sono equivalenti.

L'unico delimitatore riconosciuto tra una parte di data e ora e una parte di secondi frazionari è il punto decimale.

Le parti di data e ora possono essere separate da T invece che da uno spazio. Ad esempio, "2012-12-31 11:30:45" "2012-12-31T11: 30: 45" sono equivalenti.

Come una stringa senza delimitatori in formato "AAAAMMGGHHMMSS" o "AAMMGGHHMMSS", a condizione che la stringa abbia senso come data. Ad esempio, "20070523091528" e "070523091528" vengono interpretati come "2007-05-23 09:15:28", ma "071122129015" è illegale (ha una parte di minuti senza senso) e diventa "0000-00-00 00: 00:00' .

Come numero in formato AAAAMMGGHHMMSS o AAAAMMGHHMMSS, a condizione che il numero abbia senso come data. Ad esempio, 19830905132800 e 830905132800 vengono interpretati come "1983-09-05 13:28:00".


3

A quale database ti stai collegando? So che Oracle può essere pignolo riguardo ai formati di data e adora il formato ISO 8601 .

** Nota: Oops, ho appena letto che sei su MySQL. Basta formattare la data e provarlo come una chiamata SQL diretta separata per il test.

In Python, puoi ottenere una data ISO come

now.isoformat()

Ad esempio, a Oracle piacciono le date come

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

A seconda del database, se è Oracle potrebbe essere necessario TO_DATE:

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

L'utilizzo generale di TO_DATE è:

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

Se si utilizza un altro database (ho visto il cursore e ho pensato a Oracle; potrei sbagliarmi) quindi controlla i loro strumenti di formattazione della data. Per MySQL è DATE_FORMAT () e per SQL Server è CONVERT.

Anche l'utilizzo di uno strumento come SQLAlchemy rimuoverà differenze come queste e ti semplificherà la vita.


Non consiglio di usare datetime.isoformat () perché se usi un oggetto sensibile al fuso orario, la stringa generata include i dati del fuso orario e non corrisponde più al formato mysql richiesto.
Frankster

0

Se stai usando solo un datetime.date python (non un datetime.datetime completo), esegui semplicemente il cast della data come stringa. Questo è molto semplice e funziona per me (mysql, python 2.7, Ubuntu). La colonna published_dateè un campo data MySQL, la variabile 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:
    ...

0

quando si inserisce in t-sql

questo fallisce:

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

questo funziona:

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

modo semplice:

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.