Insertion d'un objet Python datetime.datetime dans MySQL

120

J'ai une colonne de date dans une table MySQL. Je souhaite insérer un datetime.datetime()objet dans cette colonne. Que dois-je utiliser dans l'instruction d'exécution?

J'ai essayé:

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

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

J'obtiens une erreur comme: "TypeError: not all arguments converted during string formatting" Que dois-je utiliser à la place de %s?

Peter Mortensen
la source
vous avez manqué des citations autour%s cursor.execute("INSERT INTO table (name, id, datecolumn) VALUES (%s, %s , '%s')",("name", 4,now))
Sheshnath

Réponses:

198

Pour un champ de temps, utilisez:

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

Je pense que strftime s'applique également à datetime.

g33kz0r
la source
4
Assurez-vous également que le nom de votre colonne n'est pas un mot réservé . Il m'a fallu 30 minutes pour réaliser que le nom "current_date" causait des problèmes ... ugh!
Pakman
2
Que contient timecet exemple?
James McMahon
1
J McMahon: le temps est un module Python.
dstromberg le
Que faire si quelqu'un veut récupérer la seule année, mois, jour?
Pooja Khatri le
42

Vous obtenez probablement l'erreur TypeError car vous avez besoin de guillemets autour de la valeur de la colonne de données.

Essayer:

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

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

En ce qui concerne le format, j'ai eu du succès avec la commande ci-dessus (qui comprend les millisecondes) et avec:

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

J'espère que cela t'aides.

Edvinas
la source
8
Vous ne pouvez pas avoir des guillemets autour %sde pymsql.
Martin Thoma
1
Les citations autour du troisième% s provoquent une erreur lorsque j'essaye ceci.
realjin
13

Essayez d'utiliser now.date()pour obtenir un Dateobjet plutôt qu'un fichier DateTime.

Si cela ne fonctionne pas, la conversion en une chaîne devrait fonctionner:

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
la source
N'avez-vous pas besoin d'ajouter des guillemets autour des paramètres de chaîne, c'est-à-dire "... VALUES ('% s', '% s', '% s')"
Gareth Simpson
5

Utilisez la méthode Python datetime.strftime(format), où 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')))

Fuseaux horaires

Si les fuseaux horaires sont un problème, le fuseau horaire MySQL peut être défini pour UTC comme suit:

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

Et le fuseau horaire peut être défini en Python:

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

Documentation MySQL

MySQL reconnaît les valeurs DATETIME et TIMESTAMP dans ces formats:

Sous forme de chaîne au format «AAAA-MM-JJ HH: MM: SS» ou «AA-MM-JJ HH: MM: SS» . Une syntaxe «assouplie» est également autorisée ici: tout caractère de ponctuation peut être utilisé comme délimiteur entre les parties de date ou d'heure. Par exemple, "2012-12-31 11:30:45", "2012 ^ 12 ^ 31 11 + 30 + 45", "2012/12/31 11 * 30 * 45" et "2012 @ 12 @ 31 11 ^ 30 ^ 45 'sont équivalents.

Le seul délimiteur reconnu entre une partie de date et d'heure et une partie de fraction de seconde est le point décimal.

Les parties de date et d'heure peuvent être séparées par T plutôt que par un espace. Par exemple, «2012-12-31 11:30:45» «2012-12-31T11: 30: 45» sont équivalents.

En tant que chaîne sans délimiteurs au format «AAAAMMJJHHMMSS» ou «AAMMJJHHMMSS», à condition que la chaîne ait un sens comme date. Par exemple, «20070523091528» et «070523091528» sont interprétés comme «2007-05-23 09:15:28», mais «071122129015» est illégal (il a une partie minute absurde) et devient «0000-00-00 00: 00:00 '.

En tant que nombre au format AAAAMMJJHHMMSS ou AAMMJJHHMMSS, à condition que le nombre ait un sens en tant que date. Par exemple, 19830905132800 et 830905132800 sont interprétés comme «1983-09-05 13:28:00».

Christopher Peisert
la source
3

À quelle base de données vous connectez-vous? Je sais qu'Oracle peut être pointilleux sur les formats de date et aime le format ISO 8601 .

** Remarque: Oups, je viens de lire que vous êtes sur MySQL. Formatez simplement la date et essayez-la comme un appel SQL direct distinct à tester.

En Python, vous pouvez obtenir une date ISO comme

now.isoformat()

Par exemple, Oracle aime les dates comme

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

En fonction de votre base de données, s'il s'agit d'Oracle, vous devrez peut-être TO_DATE:

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

L'utilisation générale de TO_DATE est:

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

Si vous utilisez une autre base de données (j'ai vu le curseur et j'ai pensé à Oracle; je peux me tromper), vérifiez leurs outils de format de date. Pour MySQL c'est DATE_FORMAT () et SQL Server c'est CONVERT.

L'utilisation d'un outil comme SQLAlchemy supprimera également de telles différences et vous facilitera la vie.

Ryan Christensen
la source
Je ne recommande pas d'utiliser datetime.isoformat () car si vous utilisez un objet prenant en charge le fuseau horaire, la chaîne générée comprend des données de fuseau horaire et ne correspond plus au format mysql requis.
frankster
0

Si vous utilisez simplement un datetime.date python (pas un datetime.datetime complet), convertissez simplement la date sous forme de chaîne. C'est très simple et fonctionne pour moi (mysql, python 2.7, Ubuntu). La colonne published_dateest un champ de date MySQL, la variable python publish_dateest 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
la source
0

lors de l'insertion dans t-sql

cela échoue:

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

cela marche:

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

moyen facile:

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
la source