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', ..)
将它们转换为整数。
解释所有对数组的作用(按顺序):
- 爆炸
,
- trim白色space如
,
逗号space会留下白色space
- 过滤器将删除任何虚假元素,例如
,,
空注释 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)
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
。
干杯!
我已经在这个问题上工作了 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', ..)
将它们转换为整数。
解释所有对数组的作用(按顺序):
- 爆炸
,
- trim白色space如
,
逗号space会留下白色space - 过滤器将删除任何虚假元素,例如
,,
空注释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)
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
。
干杯!