Tenga cuidado con el uso de interpolación de cadenas para consultas SQL, ya que no escapará de los parámetros de entrada correctamente y dejará su aplicación abierta a vulnerabilidades de inyección SQL. La diferencia puede parecer trivial, pero en realidad es enorme .
Incorrecto (con problemas de seguridad)
c.execute("SELECT * FROM foo WHERE bar = %s AND baz = %s" % (param1, param2))
Correcto (con escape)
c.execute("SELECT * FROM foo WHERE bar = %s AND baz = %s", (param1, param2))
Se suma a la confusión de que los modificadores utilizados para vincular parámetros en una declaración SQL varían entre las diferentes implementaciones de la API de base de datos y que la biblioteca cliente mysql utiliza una printf
sintaxis de estilo en lugar del más comúnmente aceptado '?' marcador (usado por ej. python-sqlite
).
printf
estilo%s
, y estaba algo aterrorizado de estar escribiendo consultas vulnerables. ¡Gracias por aclarar esa preocupación! :)c.execute("SELECT * FROM foo WHERE bar = %s", (param1,))
Tienes algunas opciones disponibles. Querrá sentirse cómodo con la iterpolación de cadenas de Python. ¿Cuál es un término que podría tener más éxito buscando en el futuro cuando quiera saber cosas como esta?
Mejor para consultas:
some_dictionary_with_the_data = { 'name': 'awesome song', 'artist': 'some band', etc... } cursor.execute (""" INSERT INTO Songs (SongName, SongArtist, SongAlbum, SongGenre, SongLength, SongLocation) VALUES (%(name)s, %(artist)s, %(album)s, %(genre)s, %(length)s, %(location)s) """, some_dictionary_with_the_data)
Teniendo en cuenta que probablemente ya tenga todos sus datos en un objeto o diccionario, el segundo formato le conviene más. También apesta tener que contar "% s" apariciones en una cadena cuando tienes que volver y actualizar este método en un año :)
fuente
Los documentos vinculados dan el siguiente ejemplo:
cursor.execute (""" UPDATE animal SET name = %s WHERE name = %s """, ("snake", "turtle")) print "Number of rows updated: %d" % cursor.rowcount
Entonces solo necesita adaptar esto a su propio código, ejemplo:
cursor.execute (""" INSERT INTO Songs (SongName, SongArtist, SongAlbum, SongGenre, SongLength, SongLocation) VALUES (%s, %s, %s, %s, %s, %s) """, (var1, var2, var3, var4, var5, var6))
(Si SongLength es numérico, es posible que deba usar% d en lugar de% s).
fuente
%s
allí sin importar qué tipo. @sheki: SíEn realidad, incluso si su variable (SongLength) es numérica, aún tendrá que formatearla con% s para vincular el parámetro correctamente. Si intenta utilizar% d, obtendrá un error. Aquí hay un pequeño extracto de este enlace http://mysql-python.sourceforge.net/MySQLdb.html :
Para realizar una consulta, primero necesita un cursor y luego puede ejecutar consultas en él:
c=db.cursor() max_price=5 c.execute("""SELECT spam, eggs, sausage FROM breakfast WHERE price < %s""", (max_price,))
En este ejemplo, max_price = 5 ¿Por qué, entonces, usar% s en la cadena? Porque MySQLdb lo convertirá en un valor literal de SQL, que es la cadena '5'. Cuando finalice, la consulta dirá "... DONDE precio <5".
fuente
Como alternativa a la respuesta elegida, y con la misma semántica segura de Marcel, aquí hay una forma compacta de usar un diccionario Python para especificar los valores. Tiene la ventaja de ser fácil de modificar a medida que agrega o elimina columnas para insertar:
meta_cols=('SongName','SongArtist','SongAlbum','SongGenre') insert='insert into Songs ({0}) values ({1})'. .format(','.join(meta_cols), ','.join( ['%s']*len(meta_cols) )) args = [ meta[i] for i in meta_cols ] cursor=db.cursor() cursor.execute(insert,args) db.commit()
Donde meta es el diccionario que contiene los valores para insertar. La actualización se puede realizar de la misma forma:
meta_cols=('SongName','SongArtist','SongAlbum','SongGenre') update='update Songs set {0} where id=%s'. .format(','.join([ '{0}=%s'.format(c) for c in meta_cols ])) args = [ meta[i] for i in meta_cols ] args.append( songid ) cursor=db.cursor() cursor.execute(update,args) db.commit()
fuente
La primera solución funciona bien. Quiero agregar un pequeño detalle aquí. Asegúrese de que la variable que está intentando reemplazar / actualizar tendrá que ser de tipo str. Mi tipo de mysql es decimal pero tuve que hacer que la variable de parámetro fuera str para poder ejecutar la consulta.
temp = "100" myCursor.execute("UPDATE testDB.UPS SET netAmount = %s WHERE auditSysNum = '42452'",(temp,)) myCursor.execute(var)
fuente
Aquí tienes otra forma de hacerlo. Está documentado en el sitio web oficial de MySQL. https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html
En el espíritu, está usando la misma mecánica de la respuesta de @Trey Stout. Sin embargo, encuentro este más bonito y más legible.
insert_stmt = ( "INSERT INTO employees (emp_no, first_name, last_name, hire_date) " "VALUES (%s, %s, %s, %s)" ) data = (2, 'Jane', 'Doe', datetime.date(2012, 3, 23)) cursor.execute(insert_stmt, data)
Y para ilustrar mejor cualquier necesidad de variables:
NB: tenga en cuenta el escape que se está haciendo.
employee_id = 2 first_name = "Jane" last_name = "Doe" insert_stmt = ( "INSERT INTO employees (emp_no, first_name, last_name, hire_date) " "VALUES (%s, %s, %s, %s)" ) data = (employee_id, conn.escape_string(first_name), conn.escape_string(last_name), datetime.date(2012, 3, 23)) cursor.execute(insert_stmt, data)
fuente