MySQL - 如何在 table 中 select 行,其中 id 值在另一个 table 中的逗号分隔字段中?

MySQL - How to select rows in a table where id value is in a comma delimited field in another table?

我已经在这个问题上工作了 3 天了,我的眼睛睡眼惺忪。 我有一个包含客户姓名、地址、电子邮件的 SQL "customers" table 和一个名为 "venue" 的字段,其中包含逗号分隔的一组 "id"他们感兴趣的培训课程地点。(如:18,22,35,41)

我有第二个 table,叫做 "venue",它拥有所有课程的场地。 每门课程都是 "venue" table 中的单独一行,具有自动递增 ID。 "customers" table 中的场地字段是客户在注册时 select 编辑的场地 table 中行 "id" 的集合。

一旦客户注册并被传送到 "my interests" 页面,我想通过输出 "id" 的每个 "id" 的行数据来显示他们注册感兴趣的课程34=] table 保存在客户 table 的 "customer.venue" 字段中。

我希望这是有道理的...

我的客户select

$sqlc = "Select * from customers ORDER BY id DESC LIMIT 1";

我的场地selection

$venue = $result['venue'];

我当前的 "venue" select 代码不起作用

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

有什么问题请提出,谢谢观看

我认为你应该这样写这段代码:

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

现在除非我误解了问题:

field [input] called "venue" containing a comma delimited set

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

然后这一点:

I have a second table called "venue" which holds the venues of all courses. Each course is a separate row

也就是说id是场地的主键

看来您的输入是分隔列表,并且您的 table 具有正确的 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. trim白色space如, 逗号space会留下白色space
  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。多查询注入可能无论如何都无法使用 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,在这种情况下更“合适”。

最后一件事是,如果将这些存储在与客户有关系的单独 table 中,您可以在 MySql 中完成所有操作。数据库中的 CSV 数据通常效果不佳。您只需要一个包含 2 列的 table。

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

干杯!