Вы не можете использовать заполнители для идентификаторов - только для буквенных значений.
Я не знаю, что предложить в этом случае, так как ваша функция принимает базу данных 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
Я хотел бы подчеркнуть еще рассуждение позади не просто заменить слово (SQL-инъекции). Кроме этого, хороший ответ. – deets
@deets: Да, в общем, однако, здесь не существует уязвимости SQL-инъекции, потому что имя столбца встроено в код. В этом конкретном случае безопасно использовать форматирование строк для построения запроса. – mhawke
Спасибо за ваши ответы. Вы имеете в виду, что я не могу использовать '?' для имени столбца? – allenwang