MySQL-如何在另一个表的逗号分隔字段中选择ID值所在的表中的行?

时间:2018-09-03 20:45:02

标签: php mysql select comma delimited

我已经在这个问题上工作了3天,并且眼神呆滞。 我有一个SQL“客户”表,其中包含客户名称,地址,电子邮件,以及一个名为“ venue”的字段,其中包含以逗号分隔的一组他们感兴趣的培训地点的“ id”。(例如:18, 22,35,41)

我还有一个名为“ venue”的表,其中包含所有课程的地点。 每个课程在“地点”表中都是单独的行,并带有自动递增的ID。 “客户”表中的场所字段是场所表中客户在注册时选择的“ 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 个答案:

答案 0 :(得分:1)

现在,除非我误解了这个问题:

  

称为“地点”的字段[输入]包含逗号分隔的集合

换句话说,我们可以说$result['venue']就像1,2,3,4

然后这一点:

  

我还有一个名为“ venue”的表,其中包含所有课程的地点。每门课程都是单独的一行

换句话说,我们可以说id是场所的主键。

所以看来您的输入是分隔列表,并且您的表具有正确的ID。为此,我们可以只IN并提供ID列表。

可以肯定的是,在这种情况下,您只需将它们插入查询中即可(id不需要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', ..)会将其转换为整数。

要解释对数组所做的所有操作(按顺序):

  1. ,炸毁
  2. 修剪空白,例如,逗号会留下空白
  3. 过滤器将删除所有虚假元素,例如,,空笔记0就是其中的一部分
  4. 将类型转换为int有几个原因。
  5. 然后我们再次内爆。

这似乎有点多余,但是可以清理用户提供的输入。例如,考虑以下内容:

 $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)

Sandbox

P.S。 mutli-query注入可能无论如何都不适用于PHP的“现代”版本,但这只是一个示例

在性能方面,这样做会更好,因为它可以正确使用场所中的索引。

我认为您已经使它复杂化了。

@Taha Asgari 是正确的,因为您的论点倒退了。这是一个简单的错误,因为它是要在列表中的数据库中查找内容。并非相反,或者至少这是它的常用方式。

一个例子是这样的:

     //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

干杯!

答案 1 :(得分:0)

我认为您应该像这样编写这段代码:

$sqlcp = "SELECT * FROM venue WHERE FIND_IN_SET(id,'$venue')";