Zakariyya / blog

https://zakariyya.github.io/blog/
6 stars 1 forks source link

索引问题:创建唯一索引的时候,需要根据一些条件进行过滤 | 虚拟列 #159

Open Zakariyya opened 1 year ago

Zakariyya commented 1 year ago
CREATE TABLE `tenant_fans`  (
  `id` bigint(20) NOT NULL COMMENT '主键',
  `fans_id` bigint(20) NOT NULL COMMENT '厂家客户的id,这里是tenantId',
  `quota` decimal(10, 2) NOT NULL COMMENT '余额',
  `gtva` decimal(10, 2) NOT NULL COMMENT '总交易额',
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '名字',
  `contacts` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '联系人',
  `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '邮箱',
  `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '地址',
  `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '电话',
  `status` tinyint(1) NOT NULL COMMENT '状态:0未启用,1启用',
  `tenant_id` bigint(20) NOT NULL COMMENT '租户id',
  `create_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `delete_flag` tinyint(1) NOT NULL COMMENT '删除标识:0未删除,1删除',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '厂家客户表' ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

以上是我的表,这里的 delete_flag 是一个逻辑删除的标识作用,1的时候为删除 我的问题是:我需要建立一个唯一索引,字段分别是:tenant_id,fans_id。但是这个唯一索引必须把delete_flag = 1排除掉。

AI 第一次的回答

CREATE UNIQUE INDEX idx_tenant_fans_tenant_id_fans_id
ON tenant_fans (tenant_id, fans_id)
WHERE delete_flag != 1;

但是我实际操作出现以下错误:

1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE delete_flag != 1' at line 3

AI 第二次的回答

MySQL并不支持在索引创建语句中使用WHERE子句来过滤行。

作为替代方案,你可以使用虚拟列来实现你的需求。虚拟列是根据表中其他列的值计算出的计算列,你可以在虚拟列上创建索引并排除delete_flag = 1的行。下面是一个示例:

首先,你需要添加一个虚拟列来存储delete_flag的值:

ALTER TABLE tenant_fans ADD COLUMN delete_flag_virtual TINYINT(1) GENERATED ALWAYS AS (CASE WHEN delete_flag = 1 THEN NULL ELSE delete_flag END) VIRTUAL;

然后,你可以在虚拟列上创建唯一索引:

CREATE UNIQUE INDEX idx_tenant_fans_tenant_id_fans_id
ON tenant_fans (tenant_id, fans_id, delete_flag_virtual);

这个语句将在tenant_fans表上创建一个唯一索引,该索引包含tenant_id、fans_id和delete_flag_virtual三个字段。由于虚拟列中的delete_flag值为NULL,所以只有delete_flag = 0的行才会被索引。

请记得,虚拟列只适用于MySQL 5.7及以上版本。

非常抱歉之前的回答中的错误造成了困扰。希望这次的解决方案能够满足你的需求。


实际操作完美,很赞