web-dev-qa-db-fra.com

Psycopg2 Insérer dans une table avec des espaces réservés

C'est peut-être une question plutôt idiote, mais qu'est-ce que je fais mal ici? Cela crée la table mais le INSERT INTO ne fonctionne pas, je suppose que je fais quelque chose de mal avec les espaces réservés

conn = psycopg2.connect("dbname=postgres user=postgres")
cur = conn.cursor()
escaped_name = "TOUR_2"
cur.execute('CREATE TABLE %s(id serial PRIMARY KEY, day date, elapsed_time varchar,    net_time varchar, length float, average_speed float, geometry GEOMETRY);' % escaped_name)

cur.execute('INSERT INTO %s (day,elapsed_time, net_time, length, average_speed, geometry) VALUES (%s, %s, %s, %s, %s, %s)', (escaped_name, day ,time_length,  time_length_net, length_km, avg_speed,  myLine_ppy))

conn.commit()
cur.close()
conn.close()

L'appel INSERT INTO ne fonctionne pas, il me donne

cur.execute('INSERT INTO %s (day,elapsed_time, net_time, length, average_speed,  
geometry) VALUES (%s, %s, %s, %s, %s, %s)'% (escaped_name, day ,time_length,  
time_length_net, length_km, avg_speed,  myLine_ppy))
psycopg2.ProgrammingError: syntax error at or near ":"
LINE 1: ...h, average_speed, geometry) VALUES (2013/09/01 , 2:56:59, 02...

Quelqu'un peut m'aider sur celui-ci? Merci beaucoup!

14
Timothy Dalton

Vous utilisez le formatage de chaîne Python et il s’agit d’une idée très mauvaise (TM). Pensez SQL-injection. La bonne façon de le faire est d'utiliser des variables liées:

cur.execute('INSERT INTO %s (day, elapsed_time, net_time, length, average_speed, geometry) VALUES (%s, %s, %s, %s, %s, %s)', (escaped_name, day, time_length, time_length_net, length_km, avg_speed, myLine_ppy))

où le tuple de paramètres est donné en tant que second argument de execute(). De plus, vous n’avez besoin d’échapper à aucune valeur, psycopg2 fera l’échappement pour vous. Dans ce cas particulier, il est également suggéré de ne pas transmettre le nom de la table dans une variable (escaped_name) mais de l'intégrer dans la chaîne de requête: psycopg2 ne sait pas comment citer les noms de tables et de colonnes, mais uniquement les valeurs.

Voir la documentation de psycopg2:

http://www.psycopg.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries

Si vous souhaitez générer l'instruction SQL par programme, la méthode habituelle consiste à utiliser le formatage Python pour l'instruction et la liaison de variable pour les arguments. Par exemple, si vous avez le nom de la table dans escaped_name, vous pouvez faire:

query = "INSERT INTO %s (col1, ...) VALUES (%%s, ...)" % escaped_name
curs.execute(query, args_Tuple)

Évidemment, pour utiliser des espaces réservés dans votre requête, vous devez citer tout % introduisant un argument lié dans le premier format.

Notez que ceci est sûr si et seulement siescaped_name est généré par votre code, ignorant toute entrée externe (par exemple, un nom de base de table et un compteur), mais il existe un risque d'injection SQL si vous utilisez des données fournies par l'utilisateur. .

25
fog

A partir de psycopg2 v2.7, il existe un moyen de le faire: voir le psycopg2.sql docs .

2
Matt