Имя переменной таблицы в sqlite - PullRequest
35 голосов
/ 14 июля 2010

Вопрос: можно ли использовать переменную в качестве имени таблицы, не используя для этого строковые конструкторы?


Информация:

Я сейчас работаю над проектом, который каталогизирует данные моей звездной симуляции. Для этого я загружаю все данные в базу данных 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.

Ответы [ 7 ]

37 голосов
/ 14 июля 2010

К сожалению, таблицы не могут быть целью замены параметров (я не нашел какого-либо точного источника, но я видел его на нескольких веб-форумах).

Если вы беспокоитесь о внедрении (Вы, вероятно, должны быть), вы можете написать функцию, которая очищает строку перед ее передачей.Так как вы ищете только имя таблицы, вы должны быть в безопасности, просто принимая буквенно-цифровые символы, удаляя все знаки препинания, такие как )(][;, и пробелы.В основном, просто держите 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'
9 голосов
/ 14 июля 2010

Я бы не разделял данные на несколько таблиц.Если вы создадите индекс для звездного столбца, у вас не возникнет проблем с эффективным доступом к данным.

4 голосов
/ 20 июня 2018

Для людей, которые ищут способ сделать таблицу переменной, я получил это от другого ответа на тот же вопрос здесь :

Он сказал следующее, и это работает. Это все цитаты из 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
1 голос
/ 13 января 2018

Попробуйте с форматированием строки:

sql_cmd = '''CREATE TABLE {}(id, column1, column2, column2)'''.format(
            'table_name')
db.execute(sql_cmd)

Замените 'table_name' по вашему желанию.

0 голосов
/ 09 апреля 2019

вы можете использовать что-то вроде этого conn = sqlite3.connect() createTable = '''CREATE TABLE %s (# );''' %dateNow) conn.execute(createTable)

в принципе, если мы хотим разделить данные в несколько таблиц в соответствии с датой прямо сейчас, например, вы хотите отслеживать систему на основе даты,

createTable = '' 'CREATE TABLE% s (#);' ''% dateNow) означает, что вы создаете таблицу с переменной dateNow, которую в соответствии с вашим языком кодирования вы можете определить dateNow как переменную для извлечениятекущая дата с вашего языка кодирования.

0 голосов
/ 02 июля 2016

Вы можете передать строку как команду 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)
0 голосов
/ 17 октября 2015

Как было сказано в других ответах, «таблицы не могут быть целью подстановки параметров», но если вы оказались в привязке, где у вас нет выбора, вот метод проверки, если предоставленное имя таблицы действительный.
Примечание: я сделал имя таблицы настоящей свиньей, пытаясь охватить все базы.

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...