2014-10-26 2 views
0

У меня есть таблица из трех столбцов id,word,essay. Я хочу сделать запрос, используя (?). Предложение sql: sql1 = "select id,? from training_data". Мой код ниже:запрос sqlite3 с python с использованием '?'

def dbConnect(db_name,sql,flag): 
    conn = sqlite3.connect(db_name) 
    cursor = conn.cursor() 
    if (flag == "danci"): 
     itm = 'word' 
    elif flag == "wenzhang": 
     itm = 'essay' 
    n = cursor.execute(sql,(itm,)) 
    res1 = cursor.fetchall() 
    return res1 

Однако, когда я print dbConnect("data.db",sql1,"danci") В результате я получил это [(1,'word'),(2,'word'),(3,'word')...]. Что я действительно хочу, чтобы это [(1,'the content of word column'),(2,'the content of word column')...]. Что мне делать ? Пожалуйста, дайте мне несколько идей.

ответ

3

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

Я не знаю, что предложить в этом случае, так как ваша функция принимает базу данных nasme, строку SQL и флаг, чтобы сказать, как изменить эту строку. Я думаю, что было бы лучше, чтобы пройти только первые два, и написать что-то вроде

sql = { 
    "danci": "SELECT id, word FROM training_data", 
    "wenzhang": "SELECT id, essay FROM training_data", 
} 

, а затем вызвать его с одним из

dbConnect("data.db", sql['danci']) 

или

dbConnect("data.db", sql['wenzhang']) 

Но многое зависит почему вы спрашиваете dbConnect, чтобы выбрать столбцы для извлечения на основе строки, переданной извне; это необычный дизайн.


Update - SQL Injection

Проблемы с SQL injection и tainteddata хорошо задокументированы, но вот резюме.

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

Такая информация варьируется от очевидного - параметры, переданные в командной строке, - к неясным - если переменная среды PATH модифицируема, тогда кто-то может побудить программу выполнить совершенно другой файл из предполагаемого.

Perl обеспечивает прямую помощь, чтобы избежать таких ситуаций с Taint Checking, но SQL Injection - это открытая дверь, которая здесь важна.

Предположим, что вы берете значение для столбца базы данных из не проверенного внешнего источника, и это значение отображается в вашей программе как $val. Затем, если вы напишете

my $sql = "INSERT INTO logs (date) VALUES ('$val')"; 
$dbh->do($sql); 

тогда, похоже, все будет хорошо. Например, если $val установлен в 2014-10-27 тогда $sql становится

INSERT INTO logs (date) VALUES ('2014-10-27') 

и все в порядке.Но теперь предположим, что наши данные предоставляются кем-то менее щепетильны или совершенно злыми, и ваш $val, возникнув в другом месте, содержит этот

2014-10-27'); DROP TABLE logs; SELECT COUNT(*) FROM security WHERE name != ' 

Теперь это не выглядит так хорошо. $sql устанавливается на это (с добавлением новых строк)

INSERT INTO logs (date) VALUES ('2014-10-27'); 
DROP TABLE logs; 
SELECT COUNT(*) FROM security WHERE name != '') 

, который добавляет запись в таблицу logs, как и раньше, в конце затем идет вперед и падает весь logs таблицу и подсчитывает количество записей в таблице security. Это не то, о чем мы имели в виду, и что-то, над чем мы должны защищаться.

Непосредственным решением является использование заполнители? в подготовили заявление, а затем передавая фактические значения в вызове execute. Это не только ускоряет работу, потому что оператор SQL может быть подготовлен (скомпилирован) только один раз, но защищает базу данных от вредоносных данных с помощью , цитируя для каждого заданного значения для типа данных, и : escaping любые встроенные кавычки, невозможно закрыть одно утверждение, а другое открыть другое.

Вся эта концепция была humourised в Randall Munroe's excellent XKCD comic

+0

Я хотел бы подчеркнуть еще рассуждение позади не просто заменить слово (SQL-инъекции). Кроме этого, хороший ответ. – deets

+0

@deets: Да, в общем, однако, здесь не существует уязвимости SQL-инъекции, потому что имя столбца встроено в код. В этом конкретном случае безопасно использовать форматирование строк для построения запроса. – mhawke

+0

Спасибо за ваши ответы. Вы имеете в виду, что я не могу использовать '?' для имени столбца? – allenwang

Смежные вопросы