如何删除复合 MySQL 约束 and/or 约束中使用的一列? (考虑到所描述的限制。)

How to drop a composite MySQL constraint and/or one column used in the constraint? (Allowing for limitations described.)

在 MySQL 5.0.45 数据库中,我想删除一个 2 列 UNIQUE 约束,因为它包含一个我要删除的列。两列 UNIQUE 约束中包含的其中一列也在同一个 table 中受到 FK 约束 - 但是我认为这与以下内容无关。

以下示例 tables 和数据是虚构的,但它们模仿了我真实的 tables 的形式(约束、关系),并且在我尝试修改它们时导致相同的问题.

在示例中,我想从书中删除 UNIQUE(library_id, external_id) 约束。 (因为我想删除 external_id 列。)

-- Libraries
CREATE TABLE library (
  id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL UNIQUE
  -- other columns
) ENGINE=INNODB;

-- Each book belongs to a library.
-- Each library has its own ID for the book (which we call
-- external_id).  Each library should have allocated a
-- given external ID only once, but across libraries the
-- same external ID may have been allocated more than once.

CREATE TABLE book (
  id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL,
  library_id INTEGER NOT NULL,
    CONSTRAINT book_library_id_fkey FOREIGN KEY(library_id) REFERENCES library(id),
  external_id VARCHAR(20) NOT NULL,
  UNIQUE(library_id, external_id)
  -- other columns
) ENGINE=INNODB;

-- Made up example data
INSERT INTO library(id, name) VALUES
  (1, "London"),
  (2, "Cardiff"),
  (3, "Dublin");
INSERT INTO book(id, name, library_id, external_id) VALUES
  (1, "Programming Lisp", 1, "PL-42"),
  (2, "Portable Lasers", 2, "PL-42"),
  (3, "Programming Lisp", 2, "PL-43");

尝试 1:直接删除不需要的列不起作用:

> ALTER TABLE book DROP COLUMN external_id;
Error: Duplicate entry '2' for key 2
SQLState:  23000
ErrorCode: 1062

我认为这会失败,因为删除该列也会从 UNIQUE 约束(即索引)中删除该列,从而使该索引只有一个索引列 - 现在包括重复值 (2 x "PL-42") .

尝试 2:仅删除索引。

以下 SO post 建议如何直接删除索引:Dropping Unique constraint from MySQL table。但是,使用 SHOW INDEX FROM book 会列出两个具有相同值的 'Key_name' 条目,'library_id':

> SHOW INDEX FROM book;
+-------+------------+--------------+-------------+
| Table | Key_name   | Seq_in_index | Column_name |
+-------+------------+--------------+-------------+
| book  | PRIMARY    |            1 | id          |
| book  | library_id |            1 | library_id  |
| book  | library_id |            2 | external_id |
+-------+------------+--------------+-------------+

[为清楚起见,省略了一些列。]

按照 post 的建议进行操作然后失败并出现一些神秘的错误,但可能是由于歧义(它在非歧义的情况下有效):

> DROP INDEX library_id ON book;
Error: Error on rename of '.\a6_head_dev$nemo\#sql-bd8_1' to '.\a6_head_dev$nemo\book' (errno: 150)
SQLState:  HY000
ErrorCode: 1025

(SHOW INDEX 在 Key_name 下报告重复值时如何删除 INDEX?)

我有一个后备选项,即在没有 external_id 列和 UNIQUE 约束的情况下重新创建整个 table,插入原始 table 中的所有内容,删除旧 table 并重新命名。

但我想知道是否有更清洁的解决方案。我想知道在 MySQL(任何版本)中是否有更好的方法来做到这一点。但不幸的是,我目前仍然使用 5.0,所以我真的需要一个适用的解决方案。

我相信这应该有效

-- drop the constraint, index and column
ALTER TABLE book DROP FOREIGN KEY book_library_id_fkey;
DROP INDEX library_id ON book;
ALTER TABLE book DROP COLUMN external_id;
-- Recreate the index and foreign key if necessary
ALTER TABLE book ADD CONSTRAINT book_library_id_fkey FOREIGN KEY(library_id) REFERENCES library(id);
ALTER TABLE books ADD KEY library_id (library_id);