【问题标题】:find_in_set and find_in_set unexpected resultfind_in_set 和 find_in_set 意外结果
【发布时间】:2019-10-05 18:35:02
【问题描述】:
USE mysql;
DROP PROCEDURE IF EXISTS ShowUsers;
DELIMITER $

CREATE PROCEDURE `ShowUsers`(IN KnownUsers varchar(500), IN KnownHosts varchar(500))
BEGIN
  SELECT
    user,host
  FROM
    user
  WHERE 
    NOT FIND_IN_SET(host, KnownHosts)
  AND
    NOT FIND_IN_SET(user, KnownUsers)
  ORDER BY user, host ASC;
END $
DELIMITER ;

使用的完整数据示例:

+-------------+-------------+
| user        | host        |
+-------------+-------------+
| knownuser1  | 192.168.1.5 |
| knownuser2  | 192.168.1.5 |
| unknownuser | 192.168.1.5 | # I want this result to show
| someuser1   | 192.168.1.6 |
| someuser2   | 192.168.1.6 |
| someuser3   | 192.168.1.6 |
| root        | localhost   |
+-------------+-------------+

我已经标记了我想通过运行程序显示的结果,基本上两个 IN 参数是已知用户,而已知主机是那些应该在这个数据库上有用户记录的主机。

这样调用函数

# users and hostnames(ips) to match for exclusion from results.
SET @Usernames = 'knownuser1,knownuser2';
SET @Hostnames = '192.168.1.5';

CALL ShowUsers(@Usernames, @Hostnames);

预期结果:

+-------------+-------------+
| user        | host        |
+-------------+-------------+
| unknownuser | 192.168.1.5 | # I want this result to show
| someuser1   | 192.168.1.6 |
| someuser2   | 192.168.1.6 |
| someuser3   | 192.168.1.6 |
| root        | localhost   |
+-------------+-------------+

实际结果:

+-------------+-------------+
| user        | host        |
+-------------+-------------+
| someuser1   | 192.168.1.6 |
| someuser2   | 192.168.1.6 |
| someuser3   | 192.168.1.6 |
| root        | localhost   |
+-------------+-------------+

解释(离开这个话题,但我想我应该澄清一下)我想让这个程序工作的原因,我有一个带有多个远程从属的主服务器,从属需要访问 masters 数据库,这意味着他们也必须拥有“root”访问权限,他们可以创建/重新配置自己的访问凭据。这样做的问题是,如果其中一台服务器遭到破坏,它将有机会向基本上所有数据库添加具有凭据的新用户。大开,可随意取用。

我可以在初始配置后锁定从属设备并手动打开门,运行更新,然后再次锁定它,这对应用程序来说非常费力并且使应用程序几乎无用。

我现在的想法是通过 cron 运行脚本运行此过程并检查未知用户/主机并将该从服务器锁定在数据库之外,直到我接受或拒绝主应用程序中的用户。

【问题讨论】:

  • 你在调用存储过程时混淆了变量的顺序。
  • 感谢您指出这一点,我已经解决了这个问题,直到无法正常工作,当我将 IP 地址添加到主机名时,我有多个用户使用一个 IP 地址编辑后的字符串,该 ip 的所有行都从结果中删除,如果我的想法是正确的,所有这些行都应该显示为没有匹配的用户。
  • 更新了问题,希望现在可以更好地阐明我的意图。
  • ...包含 IP 地址的行... 一行如何包含 IP 地址?
  • 对不起,我不明白这个问题。请提供样本数据、样本参数、实际结果和预期结果。

标签: mysql stored-procedures


【解决方案1】:

WHERE 子句中的条件是:

NOT FIND_IN_SET(host, KnownHosts) AND NOT FIND_IN_SET(user, KnownUsers)

相当于:

NOT (FIND_IN_SET(host, KnownHosts) OR FIND_IN_SET(user, KnownUsers))

这意味着您要排除以下行:
host 包含在KnownHosts 中或user 包含在KnownUsers 中。

所以对于您的示例数据,行:

unknownuser | 192.168.1.5

不会返回,因为 host = '192.168.1.5' 并且它包含KnownHosts (= '192.168.1.5') 中。

如果这是您要应用的逻辑,则可以将逻辑运算符更改为OR

NOT FIND_IN_SET(host, KnownHosts) OR NOT FIND_IN_SET(user, KnownUsers)

【讨论】:

  • 好的,这说明了它为什么不工作,你对我如何让它工作有什么建议吗,我认为它和 WHERE user != something AND host != anotherthing 一样.但显然情况并非如此。如果可能的话,我宁愿不必在脚本中循环一个数组多次运行查询。
  • 它按照要求从结果中删除匹配项,但如果来自 host1 的 user1 也被添加到 host2,它也匹配。那不是我的本意。我需要找到一种方法将我提供的用户主机对排除在结果之外,因此如果在 host2 上创建了来自 host1 的用户并且我没有传入已知的该对,那么它们将显示在结果中。这有意义吗?
  • 不,这不清楚。我的答案中的代码基于您的问题中的要求、示例数据和预期结果。如果还有其他情况和条件需要满足,那么这是一个完全不同的要求。
  • 是的,似乎是这样。我将不得不修改我的问题。
  • 当您在问题中引入新要求时,您已经获得的答案无效。这不是它的工作方式。新要求就是新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-11
  • 1970-01-01
  • 1970-01-01
  • 2011-05-08
  • 1970-01-01
  • 1970-01-01
  • 2018-01-25
相关资源
最近更新 更多