【问题标题】:Workaround in mysql for partial Index or filtered Index?mysql中部分索引或过滤索引的解决方法?
【发布时间】:2011-10-18 08:43:47
【问题描述】:

我正在使用 mysql 数据库。我知道 postgresql 和 SQL server 支持部分索引。就我而言,我想做这样的事情:

CREATE UNIQUE INDEX myIndex ON myTable (myColumn) where myColumn <> 'myText'

我想创建一个唯一的约束,但如果它是一个特定的文本,它应该允许重复。

我在 mysql 中找不到直接的方法。但是,是否有解决方法来实现它?

【问题讨论】:

    标签: mysql indexing partial partial-index


    【解决方案1】:

    过滤后的索引可以用函数索引和CASE 表达式来模拟(MySQL 8.0.13 和更新版本):

    CREATE TABLE t(id INT PRIMARY KEY, myColumn VARCHAR(100));
    
    -- NULL are not taken into account with `UNIQUE` indexes   
    CREATE UNIQUE INDEX myIndex ON t((CASE WHEN myColumn <> 'myText' THEN myColumn END));
    
    
    -- inserting excluded value twice
    INSERT INTO t(id, myColumn) VALUES(1, 'myText'), (2, 'myText');
    
    -- trying to insert different value than excluded twice
    INSERT INTO t(id, myColumn) VALUES(3, 'aaaaa');
    
    INSERT INTO t(id, myColumn) VALUES(4, 'aaaaa');
    -- Duplicate entry 'aaaaa' for key 'myIndex'
    
    SELECT * FROM t;
    

    db<>fiddle demo

    输出:

    +-----+----------+
    | id  | myColumn |
    +-----+----------+
    |  1  | myText   |
    |  2  | myText   |
    |  3  | aaaaa    |
    +-----+----------+
    

    【讨论】:

    • 我要指出的是,这样做会创建一个索引,将所有具有 myColumn=mytext 的行与所有其他行分开,该索引仍然包括 all 表的行。因此,您可以获得与过滤索引相同的索引功能,但您不会节省空间。如果您真正想要的是创建一个索引,该索引有效地仅引用表行的一小部分(例如,在处理中的订单,在数据库中的所有订单记录中),您在 MySQL AFAIK 中仍然无法做到这一点。 (通过“有效”,我的意思是只索引感兴趣的行)。
    • 接受的答案(@ravnur)可能是他发布时最好的答案,但现在这个答案是正确的,而且到目前为止要好得多。
    • 另外,如果您使用 MariaDB,则不能(从 v10.4 开始)像此答案中那样创建函数索引,但您可以创建生成的虚拟列和索引,达到了完全相同的效果。
    【解决方案2】:

    我想只有一种方法可以实现它。您可以向表中添加另一列,在其上创建索引并创建触发器或在存储过程中插入/更新以使用以下条件填充此列:

    if value = 'myText' then put null
    otherwise put value
    

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-12
      • 1970-01-01
      • 2010-11-18
      • 2022-11-18
      • 1970-01-01
      • 2011-05-07
      • 2015-09-07
      • 1970-01-01
      相关资源
      最近更新 更多