Nombre de tabla de variables en sqlite

Resuelto Narcolapser asked hace 14 años • 10 respuestas

Pregunta: ¿Es posible utilizar una variable como nombre de tabla sin tener que utilizar constructores de cadenas para hacerlo?


Información:

Estoy trabajando en un proyecto ahora mismo que cataloga datos de una simulación de estrella mía. Para hacerlo, estoy cargando todos los datos en una base de datos sqlite. Está funcionando bastante bien, pero he decidido agregar mucha más flexibilidad, eficiencia y usabilidad a mi base de datos. Planeo agregar planetoides a la simulación más adelante y quería tener una tabla para cada estrella. De esta manera no tendría que consultar una tabla de 20 m de algunos planetoides para el 1-4 k en cada sistema solar.

Me han dicho que usar constructores de cadenas es malo porque me deja vulnerable a un ataque de inyección SQL. Si bien eso no es gran cosa aquí, ya que soy la única persona con acceso a estas bases de datos, me gustaría seguir las mejores prácticas. Y también de esta manera si hago un proyecto con una situación similar donde está abierto al público, sé qué hacer.

Actualmente estoy haciendo esto:

cursor.execute("CREATE TABLE StarFrame"+self.name+" (etc etc)")

Esto funciona, pero me gustaría hacer algo más como:

cursor.execute("CREATE TABLE StarFrame(?) (etc etc)",self.name)

aunque entiendo que esto probablemente sería imposible. Aunque me conformaría con algo como

cursor.execute("CREATE TABLE (?) (etc etc)",self.name)

Si esto no es posible en absoluto, aceptaré esa respuesta, pero si alguien sabe una manera de hacerlo, que lo diga. :)

Estoy codificando en Python.

Narcolapser avatar Jul 14 '10 21:07 Narcolapser
Aceptado

Desafortunadamente, las tablas no pueden ser el objetivo de la sustitución de parámetros (no encontré ninguna fuente definitiva, pero la he visto en algunos foros web).

Si le preocupa la inyección (probablemente debería estarlo), puede escribir una función que limpie la cadena antes de pasarla. Dado que está buscando solo el nombre de una tabla, debería estar seguro de aceptar caracteres alfanuméricos, eliminando toda puntuación, como )(][;,los espacios en blanco. Básicamente, sigue A-Z a-z 0-9.

def scrub(table_name):
    return ''.join( chr for chr in table_name if chr.isalnum() )

scrub('); drop tables --')  # returns 'droptables'
Donald Miner avatar Jul 14 '2010 15:07 Donald Miner

Para las personas que buscan una forma de convertir la tabla en una variable, obtuve esto de otra respuesta a la misma pregunta aquí :

Decía lo siguiente y funciona. Todo está citado de mhawke :

No puede utilizar la sustitución de parámetros para el nombre de la tabla. Debe agregar usted mismo el nombre de la tabla a la cadena de consulta. Algo como esto:

query = 'SELECT * FROM {}'.format(table)
c.execute(query)

Una cosa a tener en cuenta es la fuente del valor del nombre de la tabla. Si proviene de una fuente que no es confiable, por ejemplo, un usuario, entonces necesita validar el nombre de la tabla para evitar posibles ataques de inyección SQL. Una forma podría ser construir una consulta parametrizada que busque el nombre de la tabla en el catálogo de la base de datos:

import sqlite3

def exists_table(db, name):
    query = "SELECT 1 FROM sqlite_master WHERE type='table' and name = ?"
    return db.execute(query, (name,)).fetchone() is not None
jubibanna avatar Jun 20 '2018 09:06 jubibanna