Подтвердить что ты не робот

Имя переменной в 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.

4b9b3361

Ответ 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)