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

Я знаю, как это сделать вручную (построение запроса прямо в PHP), но я бы хотел избежать этого и делать все свои SQL прямо в БД.

Пытался найти SO, но не смог найти никаких связанных вопросов. Извините, если это дубликат.

Благодарность

2
phil 25 Авг 2011 в 21:31

3 ответа

Лучший ответ

Я дал +1 @Marc B за умное использование FIND_IN_SET (). Он не сможет использовать индекс, поэтому производительность будет невысокой, но он должен работать.

Еще одно решение, которое может работать (но также будет медленным, потому что он не может использовать индекс):

DELETE FROM sometable 
WHERE CONCAT(',', param, ',') LIKE CONCAT('%,', idfield, ',%')

Решение, описываемое @Andrej L, на самом деле не является привязкой параметров, это интерполяция аргумента хранимой процедуры в динамическую строку SQL до подготовка его.

SET sql = CONCAT('DELETE FROM sometable WHERE idfield IN (', param, ')');
PREPARE stmt FROM sql;
EXECUTE stmt;

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

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

1
Community 23 Май 2017 в 12:19

В соответствии с http://dev.mysql.com/doc/refman/5.1/en/faqs-stored-procs.html#qandaitem-B-4-1-17, вы не можете сделать это напрямую.

Но я думаю, вы можете попробовать следующий трюк:

  1. Создайте строку ваших идентификаторов в php, например 'id1, id2, id3'.
  2. Используйте подготовленную инструкцию для привязки этого укуса на лету.

Может это поможет.

3
Andrej Ludinovskov 25 Авг 2011 в 17:38

Вы можете попробовать что-то вроде

DELETE FROM sometable WHERE FIND_IN_SET(idfield, @param)

Не знаю, сработает ли это (и у меня сейчас нет доступа к экземпляру mysql для тестирования). В основном проблема заключается в том, что если вы передадите список значений, разделенных запятыми, в параметр, это будет просто строка внутри sproc, и выполнение WHERE id IN ('1,2,3') не удастся, поскольку это просто простая строка, а не все то же, что и WHERE id IN (1,2,3). Функция find_in_set () должен позаботиться об этом.

2
Marc B 25 Авг 2011 в 17:39