如何删除复合 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);
在 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);