根据 POST 在 SQL 中搜索 - 加入 Table 中的变量
Searching in SQL per POST-Variable in joined Table
我尝试解决了一段时间,但没有找到解决方案。
我从一个充满移动设备的 table 中读取并列出它们,让用户可以根据移动设备名称和用户名搜索列表。
这是我的代码:
SELECT
*
FROM
tbl_mobdev
LEFT JOIN
tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN
tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN
tbl_user ON tbl_user.id = mobdev_user
WHERE
CONCAT(tbl_marke.marke_name,' ',tbl_mobdev_type.mobdev_type_bezeichnung) LIKE '%".$_POST['marke_name']."%'
AND
CONCAT(tbl_user.name,' ',tbl_user.vorname) LIKE '%".$_POST['user']."%'
AND
mobdev_aktiv = '1'
ORDER BY
".$_GET['sort']." ".$_GET['sort2']."
只要 tbl_mobdev.mobdev_user 包含用户 ID,一切都会按预期工作,而 table 不包含用户 ID 的行将被排除。
有什么解决方案吗?
编辑:将 "filter" 放在 tbl_user 的 LEFT JOIN 中的解决方案不起作用。将在每一行中显示一个 SQL,如下所示的结果。
如果 LIKE 仅包含某些内容,则不会加入不匹配的结果,该行不会被过滤。
SELECT mobdev_id, mobdev_type_bezeichnung, marke_name, tbl_user.name AS user_name, tbl_user.vorname AS user_vorname
FROM tbl_mobdev
LEFT JOIN tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN tbl_user ON tbl_user.id = mobdev_user
AND CONCAT( tbl_user.name, ' ', tbl_user.vorname ) LIKE '%%'
WHERE CONCAT( tbl_marke.marke_name, ' ', tbl_mobdev_type.mobdev_type_bezeichnung ) LIKE '%%'
AND mobdev_aktiv = '1'
ORDER BY marke_name ASC
LIMIT 0 , 30
Edit2:将 SQL 设置为以下内容并没有改变行为。
SELECT mobdev_id, mobdev_type_bezeichnung, marke_name, tbl_user.name AS user_name, tbl_user.vorname AS user_vorname
FROM tbl_mobdev
LEFT JOIN tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN tbl_user ON tbl_user.id = mobdev_user
AND CONCAT( tbl_user.name, ' ', tbl_user.vorname ) LIKE '%G%'
WHERE CONCAT( tbl_marke.marke_name, ' ', COALESCE( tbl_mobdev_type.mobdev_type_bezeichnung, '' ) ) LIKE '%%'
AND mobdev_aktiv = '1'
ORDER BY marke_name ASC
LIMIT 0 , 30
没有匹配 $_POST['user'] 的行仍然没有被过滤掉。
我上传了一张带有模糊名称的行为示例图片,左图是 Select 没有任何过滤器,右图是 Select 带有实际用户名(模糊,但是它与 mobdev_id '3'.
中的名称完全相同
http://fs5.directupload.net/images/160404/tmdbyzws.png
如您所见,其他五行仍然存在,只是没有连接。我希望它们完全消失,因为它们与过滤器不匹配。
Edit3:好吧,我现在做到了......遗憾的是使用 PHP 以一种非常肮脏的方式。我只是把代码放在这里,如果有人对此提出更好的解决方案,请告诉我。
$query = "
SELECT
mobdev_id,
mobdev_type_bezeichnung,
marke_name,
tbl_user.name AS user_name,
tbl_user.vorname AS user_vorname
FROM
tbl_mobdev
LEFT JOIN
tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN
tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN
tbl_user ON tbl_user.id = mobdev_user
WHERE
CONCAT(tbl_marke.marke_name,' ',tbl_mobdev_type.mobdev_type_bezeichnung) LIKE '%".$_POST['marke_name']."%'
";
if($_POST['user'])
{
$query .= "
AND
CONCAT(tbl_user.name,' ',tbl_user.vorname) LIKE '%".$_POST['user']."%'
";
}
$query .= "
AND
mobdev_aktiv = '1'
ORDER BY
".$_GET['sort']." ".$_GET['sort2']."
";
问题出在行
CONCAT(tbl_user.name,' ',tbl_user.vorname) LIKE '%".$_POST['user']."%'
您在 tbl_user 上的 LEFT JOIN 将允许主查询 return 独立于该行中是否有值。但是,那个特定的 WHERE 子句行有效地覆盖了它;如果 tbl_user.name 或 tbl_user.vorname 为 null,则结果始终为 false。
如果我需要做那样的事情,我通常会把测试放在 JOIN 语句的 ON 子句中。这样它会过滤 JOINed table 存在的地方,但不会在它不存在的地方造成问题。
示例查询文本应确保 tbl_user 在需要时过滤,但在未指定任何内容时不过滤 -
SELECT
md.mobdev_id,
mdt.mobdev_type_bezeichnung,
m.marke_name,
u.name AS user_name,
u.vorname AS user_vorname
FROM
tbl_mobdev md
LEFT JOIN tbl_mobdev_type mdt
ON mdt.mobdev_type_id = md.mobdev_type
LEFT JOIN tbl_marke m
ON m.marke_id = mdt.mobdev_type_marke
LEFT JOIN tbl_user u
ON u.id = md.mobdev_user
AND CONCAT(u.name,' ',u.vorname) LIKE '%".$_POST['user']."%'
WHERE
CONCAT(m.marke_name,' ',COALESCE(mdt.mobdev_type_bezeichnung,''))
LIKE '%".$_POST['m.marke_name']."%'
AND md.mobdev_aktiv = '1'
ORDER BY
".$_GET['sort']." ".$_GET['sort2']."
两个旁白 -
- 正如 Rene M. 上面所说,这段代码是一个 SQL 注入漏洞。由于目前的应用,它可能是安全的,但我仍然不会推出它;有人拿走这个应用程序或代码片段,然后在没有进行全面审计的情况下将其转移到网上的可能性并不小,然后你就遇到了问题。练习正确操作 - 不要在代码中留下 SQL 注入漏洞。
- 请为您的 table 名字取别名!为每个字段引用完整写出每个 table 名称的查询使其非常庞大。
我尝试解决了一段时间,但没有找到解决方案。
我从一个充满移动设备的 table 中读取并列出它们,让用户可以根据移动设备名称和用户名搜索列表。
这是我的代码:
SELECT
*
FROM
tbl_mobdev
LEFT JOIN
tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN
tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN
tbl_user ON tbl_user.id = mobdev_user
WHERE
CONCAT(tbl_marke.marke_name,' ',tbl_mobdev_type.mobdev_type_bezeichnung) LIKE '%".$_POST['marke_name']."%'
AND
CONCAT(tbl_user.name,' ',tbl_user.vorname) LIKE '%".$_POST['user']."%'
AND
mobdev_aktiv = '1'
ORDER BY
".$_GET['sort']." ".$_GET['sort2']."
只要 tbl_mobdev.mobdev_user 包含用户 ID,一切都会按预期工作,而 table 不包含用户 ID 的行将被排除。
有什么解决方案吗?
编辑:将 "filter" 放在 tbl_user 的 LEFT JOIN 中的解决方案不起作用。将在每一行中显示一个 SQL,如下所示的结果。 如果 LIKE 仅包含某些内容,则不会加入不匹配的结果,该行不会被过滤。
SELECT mobdev_id, mobdev_type_bezeichnung, marke_name, tbl_user.name AS user_name, tbl_user.vorname AS user_vorname
FROM tbl_mobdev
LEFT JOIN tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN tbl_user ON tbl_user.id = mobdev_user
AND CONCAT( tbl_user.name, ' ', tbl_user.vorname ) LIKE '%%'
WHERE CONCAT( tbl_marke.marke_name, ' ', tbl_mobdev_type.mobdev_type_bezeichnung ) LIKE '%%'
AND mobdev_aktiv = '1'
ORDER BY marke_name ASC
LIMIT 0 , 30
Edit2:将 SQL 设置为以下内容并没有改变行为。
SELECT mobdev_id, mobdev_type_bezeichnung, marke_name, tbl_user.name AS user_name, tbl_user.vorname AS user_vorname
FROM tbl_mobdev
LEFT JOIN tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN tbl_user ON tbl_user.id = mobdev_user
AND CONCAT( tbl_user.name, ' ', tbl_user.vorname ) LIKE '%G%'
WHERE CONCAT( tbl_marke.marke_name, ' ', COALESCE( tbl_mobdev_type.mobdev_type_bezeichnung, '' ) ) LIKE '%%'
AND mobdev_aktiv = '1'
ORDER BY marke_name ASC
LIMIT 0 , 30
没有匹配 $_POST['user'] 的行仍然没有被过滤掉。
我上传了一张带有模糊名称的行为示例图片,左图是 Select 没有任何过滤器,右图是 Select 带有实际用户名(模糊,但是它与 mobdev_id '3'.
中的名称完全相同http://fs5.directupload.net/images/160404/tmdbyzws.png
如您所见,其他五行仍然存在,只是没有连接。我希望它们完全消失,因为它们与过滤器不匹配。
Edit3:好吧,我现在做到了......遗憾的是使用 PHP 以一种非常肮脏的方式。我只是把代码放在这里,如果有人对此提出更好的解决方案,请告诉我。
$query = "
SELECT
mobdev_id,
mobdev_type_bezeichnung,
marke_name,
tbl_user.name AS user_name,
tbl_user.vorname AS user_vorname
FROM
tbl_mobdev
LEFT JOIN
tbl_mobdev_type ON mobdev_type_id = mobdev_type
LEFT JOIN
tbl_marke ON marke_id = mobdev_type_marke
LEFT JOIN
tbl_user ON tbl_user.id = mobdev_user
WHERE
CONCAT(tbl_marke.marke_name,' ',tbl_mobdev_type.mobdev_type_bezeichnung) LIKE '%".$_POST['marke_name']."%'
";
if($_POST['user'])
{
$query .= "
AND
CONCAT(tbl_user.name,' ',tbl_user.vorname) LIKE '%".$_POST['user']."%'
";
}
$query .= "
AND
mobdev_aktiv = '1'
ORDER BY
".$_GET['sort']." ".$_GET['sort2']."
";
问题出在行
CONCAT(tbl_user.name,' ',tbl_user.vorname) LIKE '%".$_POST['user']."%'
您在 tbl_user 上的 LEFT JOIN 将允许主查询 return 独立于该行中是否有值。但是,那个特定的 WHERE 子句行有效地覆盖了它;如果 tbl_user.name 或 tbl_user.vorname 为 null,则结果始终为 false。
如果我需要做那样的事情,我通常会把测试放在 JOIN 语句的 ON 子句中。这样它会过滤 JOINed table 存在的地方,但不会在它不存在的地方造成问题。
示例查询文本应确保 tbl_user 在需要时过滤,但在未指定任何内容时不过滤 -
SELECT
md.mobdev_id,
mdt.mobdev_type_bezeichnung,
m.marke_name,
u.name AS user_name,
u.vorname AS user_vorname
FROM
tbl_mobdev md
LEFT JOIN tbl_mobdev_type mdt
ON mdt.mobdev_type_id = md.mobdev_type
LEFT JOIN tbl_marke m
ON m.marke_id = mdt.mobdev_type_marke
LEFT JOIN tbl_user u
ON u.id = md.mobdev_user
AND CONCAT(u.name,' ',u.vorname) LIKE '%".$_POST['user']."%'
WHERE
CONCAT(m.marke_name,' ',COALESCE(mdt.mobdev_type_bezeichnung,''))
LIKE '%".$_POST['m.marke_name']."%'
AND md.mobdev_aktiv = '1'
ORDER BY
".$_GET['sort']." ".$_GET['sort2']."
两个旁白 -
- 正如 Rene M. 上面所说,这段代码是一个 SQL 注入漏洞。由于目前的应用,它可能是安全的,但我仍然不会推出它;有人拿走这个应用程序或代码片段,然后在没有进行全面审计的情况下将其转移到网上的可能性并不小,然后你就遇到了问题。练习正确操作 - 不要在代码中留下 SQL 注入漏洞。
- 请为您的 table 名字取别名!为每个字段引用完整写出每个 table 名称的查询使其非常庞大。