MySQL的。使用复合UNIQUE键时无法创建架构。 ERROR 1005(HY000):(错误号:150)

时间:2015-07-23 14:31:45

标签: mysql sql

我试图创建一个简单的架构,见下文。但由于某种原因,我得到了这个奇怪的150错误。我能够将问题缩小到唯一键声明:UNIQUE KEY (fk_im_savegroups_sgcode, sscode)。如果我重构声明:UNIQUE KEY (sscode) - 它有效。

有人可以向我解释为什么我不能使用复合索引?

DROP DATABASE IF EXISTS test447;
CREATE DATABASE test447 CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE test447;


CREATE TABLE im_savegroups (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    sgcode VARCHAR(20) NOT NULL,
    PRIMARY KEY (id),
    UNIQUE KEY (sgcode)
) ENGINE=InnoDB CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;

CREATE TABLE im_savespecs (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    fk_im_savegroups_sgcode VARCHAR(20) NOT NULL,
    sscode VARCHAR(20) NOT NULL,
    max_w INT UNSIGNED,
    max_h INT UNSIGNED,
    ratio_x INT UNSIGNED,
    ratio_y INT UNSIGNED,
    quality INT UNSIGNED,
    format VARCHAR(10),
    rel_dir VARCHAR(400),
    is_retina TINYINT UNSIGNED DEFAULT 0,
    is_preferred TINYINT UNSIGNED DEFAULT 0,
    PRIMARY KEY (id),
    FOREIGN KEY (fk_im_savegroups_sgcode) REFERENCES im_savegroups (sgcode) ON DELETE CASCADE ON UPDATE CASCADE,
    UNIQUE KEY (fk_im_savegroups_sgcode, sscode)
) ENGINE=InnoDB CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;

CREATE TABLE im_originals (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    fk_im_savespecs_sscode VARCHAR(20) NOT NULL,
    name VARCHAR(255),
    alt VARCHAR(180),
    filename VARCHAR(64),
    caption VARCHAR(1024),
    credit VARCHAR(1024),
    expires_at DATETIME,
    created_at DATETIME,
    updated_at DATETIME,
    PRIMARY KEY (id),
    FOREIGN KEY (fk_im_savespecs_sscode) REFERENCES im_savespecs (sscode) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;

2 个答案:

答案 0 :(得分:1)

父级必须在该列上具有唯一键

CREATE TABLE im_savegroups (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    sgcode VARCHAR(20) NOT NULL,
    PRIMARY KEY (id),
    UNIQUE KEY (sgcode)
) ENGINE=InnoDB; -- CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;


CREATE TABLE im_savespecs (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    fk_im_savegroups_sgcode VARCHAR(20) NOT NULL,
    sscode VARCHAR(20) NOT NULL,
    max_w INT UNSIGNED,
    max_h INT UNSIGNED,
    ratio_x INT UNSIGNED,
    ratio_y INT UNSIGNED,
    quality INT UNSIGNED,
    format VARCHAR(10),
    rel_dir VARCHAR(400),
    is_retina TINYINT UNSIGNED DEFAULT 0,
    is_preferred TINYINT UNSIGNED DEFAULT 0,
    PRIMARY KEY (id),
    FOREIGN KEY (fk_im_savegroups_sgcode) REFERENCES im_savegroups (sgcode) ON DELETE CASCADE ON UPDATE CASCADE,
    UNIQUE KEY (fk_im_savegroups_sgcode, sscode),
    unique key (sscode) -- ******************************
) ENGINE=innodb CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;


CREATE TABLE im_originals (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    fk_im_savespecs_sscode VARCHAR(20) NOT NULL,
    name VARCHAR(255),
    alt VARCHAR(180),
    filename VARCHAR(64),
    caption VARCHAR(1024),
    credit VARCHAR(1024),
    expires_at DATETIME,
    created_at DATETIME,
    updated_at DATETIME,
    PRIMARY KEY (id),
    CONSTRAINT fk_orig_ss FOREIGN KEY (`fk_im_savespecs_sscode`) REFERENCES im_savespecs(sscode) ON DELETE CASCADE ON UPDATE CASCADE

) ENGINE=innodb CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;

编辑:

我遇到的最大问题是:

1)是列的一个是varchar(20),复合在其中两个,OP可能需要第二个复合。在我的书中,这些都是相当广泛的复合材料。

2)FK应该回到代码表中的唯一超薄代码(未显示或甚至存在),或者返回到pk的内部。这说明了索引优化。

我甚至会做出大胆的声明,即FK应该几乎总是回到整体,除非它是如此无法忍受的心理沉思,code本身就像邮政编码一样苗条。

答案 1 :(得分:1)

http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html

  

InnoDB允许外键引用任何索引列或组   列。但是,在引用的表中,必须有一个索引   其中引用的列被列为的第一列   同样的顺序。

强调“第一栏”。

所以只需切换唯一键中字段的顺序:

UNIQUE KEY (sscode, fk_im_savegroups_sgcode),