find_in_set和find_in_set意外结果

时间:2019-10-05 18:35:02

标签: mysql stored-procedures

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 run脚本运行此过程,并检查未知的用户/主机,并将该从属服务器锁定在数据库之外,直到我接受或拒绝主应用程序中的用户为止。 / p>

1 个答案:

答案 0 :(得分: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)