简体   繁体   English

如何仅对 MySQL 中的数据子集强制执行区分大小写的唯一索引?

[英]How to enforce case sensitive unique index only on subset of data in MySQL?

I realize MySQL has different collations I can use to enforce a case sensitive unique index, but for my particular use case, I want to enforce that only on a subset of the data.我意识到 MySQL 有不同的排序规则,我可以用来强制区分大小写的唯一索引,但对于我的特定用例,我只想对数据的一个子集强制执行。

Most of the unique IDs in the data set aren't case sensitive, so making the entire column case sensitive is not ideal.数据集中的大多数唯一 ID 不区分大小写,因此使整个列区分大小写并不理想。 I can identify which rows have case sensitive IDs also.我还可以识别哪些行具有区分大小写的 ID。

It also seems MySQL doesn't have a way of creating an index with a condition either (correct me if I'm wrong).似乎 MySQL 也没有办法创建带有条件的索引(如果我错了,请纠正我)。

Here is my schema这是我的架构

masterId - int
canonicalId - varchar
environment - int

canonicalId is the column I'm referring to, and it can be tied to different environments. canonicalId 是我所指的列,它可以绑定到不同的环境。 Right now I have a unique index on canonicalId and environment.现在我有一个关于 canonicalId 和环境的唯一索引。 Environment "7" to give an example should have case sensitive IDs, the rest do not...举个例子的环境“7”应该有区分大小写的ID,其余的不要......

What is a good way to handle this?什么是处理这个问题的好方法?

Also: I don't think making all the unique IDs case sensitive would be a good solution here.另外:我不认为让所有唯一 ID 区分大小写是一个很好的解决方案。 We get these IDs from different services and the casing could very well change on them but not represent different items.我们从不同的服务中获取这些 ID,它们的大小写很可能会发生变化,但不能代表不同的项目。 That's why I only want to enforce case sensitivity on a service is known to use case sensitive IDs.这就是为什么我只想对已知使用区分大小写 ID 的服务强制区分大小写。

I was thinking of creating a SHA-256 hash of the canonicalId for this particular environment and the actual data along with the associated hash would be stored in a separate table if needed for lookup purposes later.我正在考虑为这个特定环境创建 canonicalId 的 SHA-256 哈希,如果以后需要查找,实际数据和关联的哈希将存储在单独的表中。 I only need to ensure uniqueness in this table, as the information in the masterId column is used everywhere else in my application.我只需要确保此表中的唯一性,因为 masterId 列中的信息在我的应用程序中的其他任何地方都使用。 Not sure if that would be the best way though.不确定这是否是最好的方法。

Using a Generated Expression you can create:使用生成的表达式,您可以创建:

alter table t
add g varchar(20) charset utf8 COLLATE utf8_bin GENERATED ALWAYS AS (
   IF(environmentId=7, canonicalId, UPPER(canonicalId))
)

Note: MariaDB doesn't support explicit collation on generated columns ( MDEV-12161 ).注意:MariaDB 不支持对生成的列 ( MDEV-12161 ) 进行显式整理。

The collation on g, via explict or table defaul, needs to be case sensitive.通过 explict 或 table defaul 对 g 的排序规则需要区分大小写。

Then make environmentId , g unique:然后使environmentId , g唯一:

alter table t add unique index gunique(environmentId, g)

https://dbfiddle.uk/?rdbms=mariadb_10.3&fiddle=bba30d04eb21cc60a1c1f8993e5be6e6 https://dbfiddle.uk/?rdbms=mariadb_10.3&fiddle=bba30d04eb21cc60a1c1f8993e5be6e6

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM