Имя переменной таблицы в sqlite
Вопрос: возможно ли использовать переменную в качестве имени таблицы без необходимости использовать для этого строковые конструкторы?
Информация:
Я сейчас работаю над проектом, который каталогизирует данные моей звездной симуляции. Для этого я загружаю все данные в базу данных sqlite. Это работает довольно хорошо, но я решил добавить гораздо больше гибкости, эффективности и удобства использования для моей базы данных. Я планировал позже добавить планетоиды к симуляции и хотел иметь таблицу для каждой звезды. Таким образом, мне не пришлось бы запрашивать таблицу с 20-метровыми планетоидами для 1-4k в каждой солнечной системе.
Мне сказали, что использование строковых конструкторов плохо, потому что это делает меня уязвимым для атаки SQL-инъекцией. Хотя это не имеет большого значения, так как я единственный человек, имеющий доступ к этим базам данных, я хотел бы следовать передовым методам. И так же, если я делаю проект с похожей ситуацией, когда он открыт для публики, я знаю, что делать.
В настоящее время я делаю это:
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.
10 ответов
К сожалению, таблицы не могут быть целью замены параметров (я не нашел никакого определенного источника, но я видел это на нескольких веб-форумах).
Если вы беспокоитесь о внедрении (вероятно, так и должно быть), вы можете написать функцию, которая очищает строку перед ее передачей. Поскольку вы ищете только имя таблицы, вы должны быть в безопасности, просто принимая буквенно-цифровые символы, удаляя все знаки препинания, такие как )(][;,
и пробелы. В основном, просто держать 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'
Для людей, которые ищут способ сделать таблицу переменной, я получил это от другого ответа на тот же вопрос здесь:
Он сказал следующее, и это работает. Это все цитируется из 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
Я бы не разделил данные на несколько таблиц. Если вы создадите индекс для звездного столбца, у вас не возникнет проблем с эффективным доступом к данным.
Попробуйте с форматированием строки:
sql_cmd = '''CREATE TABLE {}(id, column1, column2, column2)'''.format(
'table_name')
db.execute(sql_cmd)
замещать 'table_name'
с твоим желанием.
Чтобы избежать жесткого кодирования имен таблиц, я использовал:
table = "sometable"
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS {} (
importantdate DATE,
somename VARCHAR,
)'''.format(table))
c.execute('''INSERT INTO {} VALUES (?, ?)'''.format(table),
(datetime.strftime(datetime.today(), "%Y-%m-%d"),
myname))
А что насчет f-Strings, гораздо более читабельно.
table = "myTableName"
condition = "ID = 5"
sql = f'''SELECT * FROM {table} WHERE {condition}'''
Как уже говорилось в других ответах, "таблицы не могут быть целью подстановки параметров", но если вы оказались в привязке, где у вас нет выбора, вот метод проверки, является ли указанное имя таблицы действительным.
Примечание: я сделал имя таблицы настоящей свиньей, пытаясь охватить все основы.
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()
Вы можете использовать что-то вроде этого
conn = sqlite3.connect()
createTable = '''CREATE TABLE %s (# );''' %dateNow)
conn.execute(createTable)
в основном, если мы хотим прямо сейчас разделить данные на несколько таблиц в соответствии с датой, например, вы хотите контролировать систему на основе даты.
createTable = '''CREATE TABLE%s (#);' ''%dateNow) означает, что вы создаете таблицу с переменной dateNow, которая в соответствии с вашим языком программирования, вы можете определить dateNow как переменную для извлечения текущей даты из вашего кода язык.
Вы можете сохранить свой запрос в файле .sql или txt и использовать метод open(). Replace() для использования переменных в любой части вашего запроса. Давний читатель, но первый плакат, поэтому прошу прощения, если что-то здесь не так.
Вы можете передать строку как команду 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)