Параметрический запрос при использовании «загрузить файл данных»

Я использую параметрические запросы для обычных вставок/обновлений из соображений безопасности.
Как это сделать для таких запросов:

LOAD DATA INFILE '/filepath' INTO TABLE mytable   

В моем случае путь к файлу каждый раз будет разным (для разных запросов). Можно ли действовать следующим образом (поскольку я не получаю никаких данных извне, файл находится на самом сервере):

 path = /filepath
 "LOAD DATA INFILE" + path + "INTO TABLE mytable"

person Mr.President    schedule 27.01.2020    source источник
comment
Ты спрашиваешь разрешения?   -  person Paul Spiegel    schedule 27.01.2020
comment
@PaulSpiegel Спасибо за ответ, сэр. У меня есть все разрешения. Поскольку все делается внутри, я подумал, что смогу отформатировать запрос, используя конкатенацию строк, и покончить с параметрическими запросами, такими как вставки/обновления. Просто хотел подтвердить то же самое.   -  person Mr.President    schedule 27.01.2020
comment
Но почему? Потому что LOAD DATA не допускается в подготовленных операторах?   -  person Paul Spiegel    schedule 27.01.2020
comment
@PaulSpiegel Я использую для этого Python MySQLdb.   -  person Mr.President    schedule 27.01.2020
comment
Так в чем же проблема? Почему бы вам не использовать параметрические запросы, как для вставок и обновлений?   -  person Paul Spiegel    schedule 27.01.2020
comment
@PaulSpiegel 1.Мне было интересно, если я не получу никаких данных для вставки извне, мне все равно нужно быть осторожным с внедрением sql. 2. Я понятия не имею, как написать для этого параметрический запрос.   -  person Mr.President    schedule 27.01.2020
comment
Это не будет отличаться от INSERT или UPDATE — вы заменяете строку (путь) заполнителем: LOAD DATA INFILE ? INTO TABLE mytable.   -  person Paul Spiegel    schedule 27.01.2020


Ответы (2)


Поскольку LOAD DATA не указан в синтаксисе SQL, разрешенном в подготовленных операторах вы не можете подготовить что-то вроде

LOAD DATA INFILE ? INTO TABLE mytable

Но SET есть в списке. Таким образом, обходным путем может быть подготовка и выполнение

SET @filepath = ?

А затем выполнить

LOAD DATA INFILE @filepath INTO TABLE mytable

Обновлять

В Python с MySQLdb должен работать следующий запрос

LOAD DATA INFILE %s INTO TABLE mytable

поскольку подготовленный оператор не используется.

person Paul Spiegel    schedule 27.01.2020
comment
Я не думаю, что ОП спрашивает о подготовленных операторах, а скорее о параметризованных операторах, которые обрабатываются на стороне клиента. См. этот ответ, который предполагает, что подготовленные операторы даже не возможны с MySQLdb. - person totalhack; 27.01.2020
comment
@totalhack - Если не используются подготовленные операторы, то я вообще не вижу проблемы. - person Paul Spiegel; 27.01.2020

Чтобы ответить на ваш вопрос «можно ли продолжать так», ваш пример кода завершится ошибкой, потому что в результирующем запросе будут отсутствовать кавычки вокруг имени файла. Если вы измените его на следующее, он может работать, но это все еще плохая идея IMO:

 path = "/filepath"
 sql = "LOAD DATA INFILE '" + path + "' INTO TABLE mytable" # note the single quotes

Хотя сегодня вы можете не принимать входные данные извне, код может остаться и быть повторно использованным/скопированным, поэтому вам следует использовать API так, чтобы избежать ваших параметров:

sql = "LOAD DATA INFILE %s INTO TABLE mytable"
cursor.execute(sql, (path,))

И не забудьте зафиксировать, если автокоммит не включен.

person totalhack    schedule 27.01.2020
comment
Большое спасибо, сэр, за устранение сомнений по поводу использования конкатенации строк. Придерживаясь вашего совета, я бы и в этом случае выбрал параметрический запрос. Это замечание об автоматической фиксации должно быть выделено полужирным шрифтом. - person Mr.President; 27.01.2020