【问题标题】:Enforce unique rows in MySQL在 MySQL 中强制执行唯一行
【发布时间】:2010-09-10 13:04:37
【问题描述】:

我在MySQL 中有一个包含 3 个字段的表,我想在其中两个字段之间强制执行唯一性。这是DDL的表格:

CREATE TABLE `CLIENT_NAMES` (
`ID` int(11) NOT NULL auto_increment,
`CLIENT_NAME` varchar(500) NOT NULL,
`OWNER_ID` int(11) NOT NULL,
PRIMARY KEY  (`ID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ID 字段是代理键(此表正在加载 ETL)。 CLIENT_NAME 是一个包含客户端名称的字段 OWNER_ID 是一个 id,表示客户所有者。

我认为我可以在 CLIENT_NAMEOWNER_ID 上使用唯一索引来强制执行此操作,

ALTER TABLE `DW`.`CLIENT_NAMES` 
ADD UNIQUE INDEX enforce_unique_idx(`CLIENT_NAME`, `OWNER_ID`);

但是 MySQL 给了我一个错误:

执行 SQL 命令更新表时出错。 指定的密钥太长;最大密钥长度为 765 字节(错误 1071)

其他人有什么想法吗?

【问题讨论】:

    标签: mysql indexing mysql-error-1071


    【解决方案1】:

    MySQL 不能对长度超过 765 字节的键强制唯一性(显然 500 个 UTF8 字符可以超过此限制)。

    1. CLIENT_NAME 真的需要 500 个字符吗?好像有点过分了。
    2. 添加一个新的(较短的)列,即 hash(CLIENT_NAME)。改为让 MySQL 强制该哈希的唯一性。

    【讨论】:

    • Unicode 是一种可变长度编码。字符的大小可以是一到四个字节,并且只有原始的 128 个 ASCII 字符被编码在一个字节中。
    【解决方案2】:

    你看过 CONSTRAINT ... UNIQUE 吗?

    【讨论】:

      【解决方案3】:

      这张桌子似乎有点奇怪;我实际上会考虑重构它。 ID 和 OWNER_ID 指的是什么,它们之间的关系是什么?

      有没有意义

      CREATE TABLE `CLIENTS` (
      `ID` int(11) NOT NULL auto_increment,
      `CLIENT_NAME` varchar(500) NOT NULL,
      # other client fields - address, phone, whatever
      PRIMARY KEY  (`ID`),
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      CREATE TABLE `CLIENTS_OWNERS` (
      `CLIENT_ID` int(11) NOT NULL,
      `OWNER_ID` int(11) NOT NULL,
      PRIMARY KEY  (`CLIENT_ID`,`OWNER_ID`),
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
      

      我真的会避免在 500 个字符的字符串上添加这样的唯一键。在两个整数上强制唯一性会更有效,而且表中的 id 应该真正引用需要 id 的东西;在您的版本中,ID 字段似乎只识别客户/所有者关系,实际上不需要单独的 id,因为它只是一个映射。

      【讨论】:

        【解决方案4】:

        Here。对于 UTF8 字符集,MySQL 每个字符最多可以使用 3 个字节。 CLIENT_NAME 为 3 x 500 = 1500 字节。将CLIENT_NAME 缩短为 250。

        稍后: +1 创建名称的哈希并将其用作键。

        【讨论】:

        • 说 UTF-8 使用 3 个字节/字符是错误的。正如您自己指出的页面所说,它可以达到该值,而在 MySQL 上无法使用的是悲观方法。
        猜你喜欢
        • 1970-01-01
        • 2011-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多