1

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

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

在示例中,我想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 帖子建议如何直接删除索引:Dropping Unique constraint from MySQL table。但是,使用SHOW INDEX FROM book列出两个具有相同值“library_id”的“Key_name”条目:

> 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 |
+-------+------------+--------------+-------------+

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

按照帖子的建议进行操作,然后失败并出现一个有点神秘的错误,但可能是由于模棱两可(它适用于非模棱两可的情况):

> 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 报告下的重复值时,如何删除 INDEX Key_name?)

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

但我想知道是否有更清洁的解决方案。我想知道在 MySQL(任何版本)中是否有更好的方法来做到这一点。但不幸的是,我目前被 5.0 困住了,所以我真的需要一个可以解决这个问题的解决方案。

4

1 回答 1

1

我相信这应该有效

-- 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);
于 2015-04-24T13:16:59.167 回答