Имя переменной в sqlite
Вопрос: Можно ли использовать переменную в качестве имени вашей таблицы без использования конструкторов строк?
Информация:
Я работаю над проектом прямо сейчас, когда каталоги данных от моделирования звезды. Для этого я загружаю все данные в базу данных sqlite. Он работает очень хорошо, но я решил добавить гораздо большую гибкость, эффективность и удобство использования в свой db. Я планирую позже добавлять планету к моделированию и хотел бы иметь таблицу для каждой звезды. Таким образом, мне не нужно было бы запрашивать таблицу из 20 млн. Планетарных частиц для 1-4к в каждой солнечной системе.
Мне сказали, что использование конструкторов строк плохо, потому что это оставляет меня уязвимым для атаки SQL-инъекции. Хотя это не так уж и важно, поскольку я единственный человек, имеющий доступ к этим dbs, я хотел бы следовать лучшим практикам. И также, если я делаю проект с аналогичной ситуацией, когда он открыт для публики, я знаю, что делать.
В настоящее время я делаю это:
cursor.execute("CREATE TABLE StarFrame"+self.name+" (etc etc)")
Это работает, но я хотел бы сделать что-то более похожее:
cursor.execute("CREATE TABLE StarFrame(?) (etc etc)",self.name)
хотя я понимаю, что это, вероятно, будет невозможно. хотя я бы согласился на что-то вроде
cursor.execute("CREATE TABLE (?) (etc etc)",self.name)
Если это не совсем возможно, я соглашусь с этим ответом, но если кто-нибудь знает, как это сделать, расскажите.:)
Я кодирую в python.
Ответы
Ответ 1
К сожалению, таблицы не могут быть целью замены параметров (я не нашел никакого определенного источника, но я видел его на нескольких веб-форумах).
Если вас беспокоит инъекция (вы, вероятно, должны быть), вы можете написать функцию, которая очищает строку перед ее передачей. Поскольку вы ищете только имя таблицы, вы должны быть в безопасности, просто принимая буквенные символы, удаляя все знаки пунктуации, такие как )(][;,
и пробельные символы. В принципе, просто держите 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'
Ответ 2
Я бы не разделил данные на несколько таблиц. Если вы создадите индекс в столбце "звезда", у вас не будет проблем с эффективностью доступа к данным.
Ответ 3
Для людей, которые ищут способ сделать таблицу переменной, я получил это от другого ответа на тот же вопрос здесь:
Он сказал следующее, и это работает. Это все цитируется из Mhawke:
Вы не можете использовать подстановку параметров для имени таблицы. Вам нужно добавить имя таблицы в строку запроса самостоятельно. Что-то вроде этого:
query = 'SELECT * FROM {}'.format(table)
c.execute(query)
Следует помнить об источнике значения для имени таблицы. Если это происходит из ненадежного источника, например, от пользователя, вам необходимо проверить имя таблицы, чтобы избежать потенциальных атак SQL-инъекций. Одним из способов может быть создание параметризованного запроса, который ищет имя таблицы из каталога БД:
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
Ответ 4
Попробуйте с форматированием строки:
sql_cmd = '''CREATE TABLE {}(id, column1, column2, column2)'''.format(
'table_name')
db.execute(sql_cmd)
Замените 'table_name'
на ваше желание.
Ответ 5
Вы можете использовать что-то вроде этого conn = sqlite3.connect() createTable = '''CREATE TABLE %s (# );''' %dateNow) conn.execute(createTable)
в основном, если мы хотим разделить данные на несколько таблиц в соответствии с датой прямо сейчас, например, вы хотите отслеживать систему на основе даты.
createTable = '' 'CREATE TABLE% s (#);' ''% dateNow) означает, что вы создаете таблицу с переменной dateNow, которая в соответствии с вашим языком кодирования позволяет определить dateNow как переменную для получения текущей даты из вашей кодировки язык.
Ответ 6
Как было сказано в других ответах, "таблицы не могут быть мишенью для замены параметров", но если вы обнаруживаете себя в привязке, где у вас нет опции, вот метод тестирования, если указано имя таблицы действительный.
Примечание. Я сделал имя таблицы реальной свинью, пытаясь охватить все базы.
import sys
import sqlite3
def delim(s):
delims="\"'`"
use_delim = []
for d in delims:
if d not in s:
use_delim.append(d)
return use_delim
db_name = "some.db"
db = sqlite3.connect(db_name)
mycursor = db.cursor()
table = 'so""m ][ `etable'
delimiters = delim(table)
if len(delimiters) < 1:
print "The name of the database will not allow this!"
sys.exit()
use_delimiter = delimiters[0]
print "Using delimiter ", use_delimiter
mycursor.execute('SELECT name FROM sqlite_master where (name = ?)', [table])
row = mycursor.fetchall()
valid_table = False
if row:
print (table,"table name verified")
valid_table = True
else:
print (table,"Table name not in database", db_name)
if valid_table:
try:
mycursor.execute('insert into ' +use_delimiter+ table +use_delimiter+ ' (my_data,my_column_name) values (?,?) ',(1,"Name"));
db.commit()
except Exception as e:
print "Error:", str(e)
try:
mycursor.execute('UPDATE ' +use_delimiter+ table +use_delimiter+ ' set my_column_name = ? where my_data = ?', ["ReNamed",1])
db.commit()
except Exception as e:
print "Error:", str(e)
db.close()
Ответ 7
Вы можете передать строку как команду SQL:
import sqlite3
conn = sqlite3.connect('db.db')
c = conn.cursor()
tablename, field_data = 'some_table','some_data'
query = 'SELECT * FROM '+tablename+' WHERE column1=\"'+field_data+"\""
c.execute(query)