mysql中部分索引或过滤索引的解决方法?

And*_*ews 9 mysql indexing partial partial-index

我正在使用mysql db.我知道postgresql和SQL server支持部分索引.在我的情况下,我想做这样的事情:

CREATE UNIQUE INDEX myIndex ON myTable (myColumn) where myColumn <> 'myText'
Run Code Online (Sandbox Code Playgroud)

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

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

Luk*_*zda 10

可以使用函数索引和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;
Run Code Online (Sandbox Code Playgroud)

db<>小提琴演示

输出:

+-----+----------+
| id  | myColumn |
+-----+----------+
|  1  | myText   |
|  2  | myText   |
|  3  | aaaaa    |
+-----+----------+
Run Code Online (Sandbox Code Playgroud)

  • 我要指出的是,这样做会创建一个索引,将具有“myColumn=mytext”的所有行与所有其他行分开,**但是**索引仍然包含*所有*表的行。因此,您可以获得与过滤索引相同的索引功能,但您“没有”节省空间。如果您真正想要的是创建一个索引,*有效地*仅引用表行的一小部分(例如,处理中的订单,数据库中的所有订单记录),您仍然无法做到MySQL AFAIK 中的那个。(“有效”是指仅对感兴趣的行建立索引)。 (3认同)
  • 另外,如果您使用的是 MariaDB,则无法(从 v10.4 开始)创建一个函数索引,如本答案所示,但您可以创建一个生成的虚拟列并对其进行索引,这可以实现完全相同的效果。 (3认同)
  • 当他发布它时,接受的答案(由@ravnur)可能是最好的,但现在这个答案是正确的答案,而且到目前为止要好得多。 (2认同)

rav*_*nur 7

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

if value = 'myText' then put null
otherwise put value
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你