MySQL - Как выбрать строки в таблице, где значение id находится в поле с разделителями-запятыми в другой таблице?
Я работаю над этой проблемой в течение 3 дней, и у меня мутные глаза. У меня есть таблица SQL "клиенты", содержащая имя клиента, адрес, адрес электронной почты и поле с именем "место проведения", содержащее набор разделенных запятыми идентификаторов мест проведения учебных курсов, в которых они заинтересованы. (Например: 18,22,35,41)
У меня есть второй стол под названием "Место проведения", в котором находятся места проведения всех курсов. Каждый курс представляет собой отдельную строку в таблице "место проведения" с идентификатором автоинкремента. Поле места в таблице "клиенты" представляет собой набор строки "id" в таблице места, которую клиент выбрал при регистрации.
После того, как клиент зарегистрирован и перенесен на страницу "мои интересы", я хотел бы отобразить курсы, в которых он зарегистрировал интерес, путем вывода данных строк каждого "id" таблицы "место проведения", которые содержатся в " customer.venue "поле таблицы клиента.
Надеюсь это имеет смысл...
Мой клиент выбирает
$sqlc = "Select * from customers ORDER BY id DESC LIMIT 1";
Мой выбор места
$venue = $result['venue'];
Мой текущий код выбора места проведения, который не работает
sqlcp = "SELECT * FROM venue WHERE FIND_IN_SET('$venue', id)";
Пожалуйста, задавайте любые вопросы, спасибо за внимание
2 ответа
Я думаю, что вы должны написать этот код как:
$sqlcp = "SELECT * FROM venue WHERE FIND_IN_SET(id,'$venue')";
Теперь, если я не понимаю вопрос:
поле [input] называется "место встречи", содержащее набор, разделенный запятыми
Другими словами мы можем сказать $result['venue']
как 1,2,3,4
,
И тогда этот бит:
У меня есть второй стол под названием "Место проведения", в котором находятся места проведения всех курсов. Каждый курс - это отдельный ряд
Другими словами, мы можем сказать, что id
является первичным ключом места.
Таким образом, кажется, что ваш ввод - это отдельный список, а ваша таблица имеет правильные идентификаторы. для этого мы можем только мы IN
и предоставить список идентификаторов.
Конечно, вы можете просто вставить их в запрос в этом случае (для идентификаторов не нужны кавычки в IN), но это не дает вам никакой защиты от сбоев.
Например:
//Please don't do this as you can get SQLInjection from the input
$sql = "SELECT * FROM venue WHERE id IN (".$result['venue'].")";
Вместо этого сделайте что-то вроде этого:
$venue = implode(',',array_map('intval',array_filter(array_map('trim', explode(',',$result['venue'])))));
$sql = "SELECT * FROM venue WHERE id IN (".$venue.")";
Обычно я бы не стал объединять, но, пожалуйста, примите к сведению array_map('intval', ..)
который преобразует их в целые.
Чтобы объяснить, что все это делает с массивом (по порядку):
- взорваться
,
- обрезать пустое пространство, такое как
,
запятая оставит пробел - Фильтр удалит все ложные элементы, такие как
,,
пустая заметка0
является частью этого - преобразовать тип в
int
по нескольким причинам. - тогда мы снова взрываемся.
Это кажется немного избыточным, но оно очищает введенный пользователем ввод. Например, рассмотрим следующее:
$v="1,,2 , 4); DROP TABLE users --";
echo "Unsafe:\n";
echo "SELECT * FROM venue WHERE id IN ({$v})\n\n";
$venue = implode(',',array_map('intval',array_filter(array_map('trim', explode(',',$v)))));
print_r($venue);
echo "Safer:\n";
echo "SELECT * FROM venue WHERE id IN ({$venue})\n\n";
Выход
Unsafe:
SELECT * FROM venue WHERE id IN (1,,2 , 4); DROP TABLE users --)
Safer:
SELECT * FROM venue WHERE id IN (1,2,4)
PS Mutli-запрос инъекций, вероятно, не будет работать в любом случае с "современной" версией PHP, но это только один пример
По производительности это будет намного лучше, потому что он может правильно использовать индексы в месте проведения.
Я думаю, что вы слишком усложнили это.
@ Таха Аскари прав, у вас есть аргументы задом наперед. Это простая ошибка, потому что она предназначена для поиска в базе данных, которая находится в списке. Не наоборот или, по крайней мере, это обычный способ его использования.
Пример таков:
//this is the correct way
SELECT * FROM venue WHERE FIND_IN_SET(1,'1,2,3,4')
//this is the way you have it
SELECT * FROM venue WHERE FIND_IN_SET('1,2,3,4', 1)
Для справки FIND_IN_SET
Тем не менее, нам не нужно использовать FIND_IN_SET
в этом случае, потому что мы можем просто использовать IN, который является более "правильным" в этом случае.
И последнее, если бы они хранились в отдельной таблице с отношением к клиенту, все это можно было бы сделать в MySql. Данные CSV в БД обычно плохо работают. Все, что вам нужно, это таблица с 2 столбцами.
//table customers_venues
customer_id
venue_id
Тогда вы могли бы сделать запрос, как это:
Select
cv.venue
from
customers AS c
JOIN
customers_venues AS cv ON cv.customer_id = c.id
JOIN
venues as v ON cv.venue_id = v.id
Но я не знаю, что сказать LIMIT 1
,
Ура!