【问题标题】:Oracle query data where column value with comma to check the value contains or notOracle 查询数据所在的列值用逗号检查值是否包含
【发布时间】:2017-10-12 18:02:57
【问题描述】:

我想查询数据以检查至少包含 1 个 IP 地址。

例如我有以下数据:

PROFILEID   PROFILE_NAME        ACTIVE  DATEADDED               ADDEDBY LOCATIONID_FK   ALLOWED_IP_ADDRESS
PF0001      Normal Working Day  Y       9/30/2017 5:53:39 PM    US0001  LC0001          192.168.183.205, 192.168.183.28
PF0004      Ramadhan            N       10/12/2017 10:38:02 AM  US0001  LC0003  
PF0002      Ramadhan            N       9/30/2017 5:55:50 PM    US0001  LC0001          192.168.183.205, 192.168.183.28
PF0003      Normal Working Day  Y       10/3/2017 5:23:05 PM    US0001  LC0003          192.168.184.20, 192.168.184.15

如您所见,ALLOWED_IP_ADDRESS 列有更多带有逗号的 ip。

现在我想检查ALLOWED_IP_ADDRESS IN ('192.168.183.28') 的查询位置,但没有结果。

SELECT PROFILEID FROM WA_BT_TBL_PROFILE P WHERE P.ALLOWED_IP_ADDRESS IN ('192.168.183.28');

如何正确查询?

【问题讨论】:

    标签: oracle


    【解决方案1】:

    您需要检查由分隔符包围的子字符串:

    SELECT PROFILEID
    FROM   WA_BT_TBL_PROFILE P
    WHERE  ', ' || P.ALLOWED_IP_ADDRESS || ', ' LIKE '%, 192.168.183.28, %';
    

    但是,更好的方法是更改​​您的数据库表,这样您就不会将多个项目存储在一个值中:

    CREATE TABLE Allowed_IP_Addresses(
      PROFILEID          VARCHAR2(20)
                         CONSTRAINT AllowIP__ProfileID__FK REFERENCES WA_BT_TBL_PROFILE( PROFILEID ),
      CLASSA             NUMBER(3,0),
      CLASSB             NUMBER(3,0),
      CLASSC             NUMBER(3,0),
      CLASSD             NUMBER(3,0),
      IP_ADDRESS         VARCHAR2(15)
                         GENERATED ALWAYS AS (CLASSA||'.'||CLASSB||'.'||CLASSC||'.'||CLASSD) VIRTUAL,
      CONSTRAINT AllowIP__P_A_B_C_D__PK PRIMARY KEY ( PROFILEID, CLASSA, CLASSB, CLASSC, CLASSD )
    );
    

    然后您可以单独存储这些值(并轻松搜索子网范围)并根据需要将其加入配置文件表。

    【讨论】:

    • @apomene WHERE ', ' || P.ALLOWED_IP_ADDRESS || ', ' LIKE 这就是该列前后添加分隔符的原因,因此在这种情况下仍会匹配。
    • @HiDayurie Dave:请注意,使用 like 的解决方案不允许您比较多个 IP 地址。您必须从表中的字符串中拆分 IP 地址,这会使事情变得相当复杂。所以请按照 MT0 给出的建议来规范化数据——这将帮助您编写更易于维护的代码,并提供更好的性能。
    【解决方案2】:

    如果您正在寻找完全匹配,您可以使用like 条件或instr 函数,但您需要在两边连接逗号,如下所示:

    select profileid
      from wa_bt_tbl_profile p
     where ', ' || p.allowed_ip_address || ',' like '%, 192.168.183.28,%'
    

    [编辑] 如果您在比较 IP 地址时不使用逗号,您可能会得到不需要的结果 - 例如,如果您使用地址 10.10.10.10 进行比较,则没有逗号的有效结果也将是 110.10.10.10、10.10.10.101、110.10.10.101 等。

    我建议您删除逗号和 IP 地址之间的空格 - 这只会使代码更难理解。

    【讨论】:

    • 是的,有什么问题?查询将返回它。这就是我在 p.allowed_ip_address 周围添加逗号的原因。
    【解决方案3】:

    改用like

    SELECT PROFILEID FROM WA_BT_TBL_PROFILE P WHERE P.ALLOWED_IP_ADDRESS LIKE '%192.168.183.28%'
    

    以上是对不良表使用的“肮脏修复”。您应该避免将连接的字符串存储在同一个条目上。 还要考虑到上述查询将对给定 IP 的子集有效。以上 IP 将保证您获得正确的结果,但是使用例如 IP 192.168.183.2,可能会带来不需要的条目,例如 192.16.183.21,...

    【讨论】:

    • LIKE '%19.168.183.25%' 将匹配 19.168.183.25 以及 219.168.183.2519.168.183.256119.168.183.250(以及许多其他)。
    • @MT0 我写的是 192.168.183.28 而不是 19.168.183.25,这意味着 280 0r 28x 不是一个选项....另外 19.168.183.256 不是一个有效的 IP,请先检查一下发布
    • @GoranStefanović。 Gyus 请想一想……在您发布之前,28x 不能是有效的结束 IP。 IP 上升到 255。280 或 281 或 289,或者....不是有效的 IP
    • @apomene:您对范围的看法是对的,但谁能说 OP 不会将地址与明天的 10.1.1.5 进行比较?
    • MT0 的示例是基于这样的假设,即 OP 并不总是与那个地址进行比较,但要求会随着时间而改变。我们应该提供可重用的查询,而不仅仅是针对特定情况的查询。
    猜你喜欢
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    • 2019-08-10
    相关资源
    最近更新 更多