【问题标题】:Supply user host pairs to be excluded from mysql results提供要从 mysql 结果中排除的用户主机对
【发布时间】:2020-02-03 22:52:24
【问题描述】:

要处理的数据:

+-------------+-------------+
| user        | host        |
+-------------+-------------+
| user1       | host1       | -
| user1       | ip1         | -
| user1       | host2       | *
| user2       | host2       | -
| user2       | ip2         | -
| unknown     | unknown     | +
| user1       | unknown     | +
| unknown     | host        | +
+-------------+-------------+

表格右侧的符号是: - 不显示 | + 显示为未知 | * 因为一个用户只能连接到一个主机,除非我已经授权它,在这种情况下,我会将用户主机对也提供给调用,它不会显示。

这就是我希望事情的工作方式。

这是我在question 的帮助下所处的位置,因为现在有一个进一步的条件需要提出一个新问题。

当前程序

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 ;

像这样调用过程

# known users and known hostnames or ips to match and exclude from results.
SET @Usernames = 'user1,user2';
SET @Hostnames = 'host1,host2,ip1,ip2'

CALL ShowUsers(@Usernames, @Hostnames);

预期结果:

+-------------+-------------+
| user        | host        |
+-------------+-------------+
| user1       | host2       | *
| unknown     | unknown     | +
| user1       | unknown     | +
| unknown     | host        | +
+-------------+-------------+

我希望能够提供多个用户:主机对(已知合法凭据)并返回不匹配的结果,因此在查询结果中仅返回可疑/非法凭据。

我已经创建了一个小提琴 https://www.db-fiddle.com/f/xb7dWXbkokHGbcPdzR7BUa/4 希望你能看到我的目标。

【问题讨论】:

  • 那么,您希望user1 仅与192.168.1.5 匹配,而user2 仅与192.168.1.6 匹配?如果是,为什么第二行 (user1, host1) 不会出现在输出中?
  • 它会使用此处提供的值,但使用不同数据的列表要长得多,为了简单起见,我缩短了问题和 user1 host1 和 user1 host2 的值,它们不是实际凭据。它们都不是,但可以使用数据构建一个表,然后使用这些凭据调用。我想这样看,凭据实际上并不重要,只是连续的两个值应该是匹配的值,如果不匹配,则返回该记录。
  • 我在想一些类似于 JSON 的东西,但 mariadb 不能正确支持它,这将是一个同步完成,我可以提交 json 与 user:host 作为 key:value 对并解决问题字符串拆分和标准选择 if !=
  • 你不需要 JSON;查看Field() 函数在两个不同的逗号分隔字符串中进行一对一匹配。我仍然不清楚为什么 user1 host1 和 user2 host2 不在输出中;否则解决方案已准备就绪
  • 他们将在这里使用给定的数据。抱歉,我没有更正电话来解释它。请耐心等待,我会更新问题,我会显示预期结果,并将集合调整为给定表格的正确数据。

标签: mysql stored-procedures mariadb


【解决方案1】:

根据我从您的问题陈述中可以理解的任何内容,您将需要使用多个字符串操作来满足您的条件(下面的内联 cmets 中的解释):

查询

SELECT
  `user`,`host`
FROM
  tbl
WHERE 

 -- NOT condition to avoid returning one-to-one mapping between `user` and `host`
 -- If `user` exist in the @Usernames, and the position of the 
 -- `user` matches with the position of the `host` in the @Hostnames
 NOT ( 
       FIND_IN_SET(`user`, @Usernames) > 0
       -- Host and User are at same position in the lists
       AND FIND_IN_SET(`user`, @Usernames) = FIND_IN_SET(`host`, @Hostnames) 
     )

 AND 

 -- NOT condition to handle `host` at the end of @Hostnames list, where 
 -- there is no corresponding `user` mapped
 NOT ( 
      FIND_IN_SET(`host`, @Hostnames) > CHAR_LENGTH(@Usernames) 
                                        - CHAR_LENGTH(REPLACE(@Usernames, ',', '')) 
                                        + 1 
     );

结果

| user    | host    |
| ------- | ------- |
| user1   | host2   |
| unknown | unknown |
| user1   | unknown |
| unknown | host    |

View on DB Fiddle

警告:@Usernames 列表中没有用户时,上述查询将不起作用。为简洁起见,我避免让条件变得更复杂来处理它。此外,我怀疑在您的实际用例中,您会遇到列表中没有用户的情况。

【讨论】:

  • 谢谢,这看起来可行。由于我将提供用户主机对,因此我将确保位置正确。
  • 不,当我向列表中添加更多用户时它会失败。不知道你明白这是我的错。我遇到的最大问题是我无法理解我希望我的小提琴能够解决的问题,但事实并非如此。看来我在这些问题上浪费了很多人的时间。
【解决方案2】:

这种结构有效(但对于大表无效):

WHERE (user, host) NOT IN ( ('u1', 'h1'), ('u2', 'h2), ... )

更多讨论,请参见“行构造函数”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-06
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多