Lỗi 1022 - Không thể viết; khóa trùng lặp trong bảng


218

Tôi đang gặp lỗi 1022 liên quan đến các khóa trùng lặp trong lệnh tạo bảng. Nhìn vào truy vấn, tôi không thể hiểu được sự trùng lặp đang diễn ra ở đâu. Bất cứ ai khác có thể nhìn thấy nó?

SQL query:

-- -----------------------------------------------------
-- Table `apptwo`.`usercircle`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS  `apptwo`.`usercircle` (

 `idUserCircle` MEDIUMINT NOT NULL ,
 `userId` MEDIUMINT NULL ,
 `circleId` MEDIUMINT NULL ,
 `authUser` BINARY NULL ,
 `authOwner` BINARY NULL ,
 `startDate` DATETIME NULL ,
 `endDate` DATETIME NULL ,
PRIMARY KEY (  `idUserCircle` ) ,
INDEX  `iduser_idx` (  `userId` ASC ) ,
INDEX  `idcategory_idx` (  `circleId` ASC ) ,
CONSTRAINT  `iduser` FOREIGN KEY (  `userId` ) REFERENCES  `apptwo`.`user` (
`idUser`
) ON DELETE NO ACTION ON UPDATE NO ACTION ,
CONSTRAINT  `idcategory` FOREIGN KEY (  `circleId` ) REFERENCES  `apptwo`.`circle` (
`idCircle`
) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE = INNODB;

MySQL said: Documentation

#1022 - Can't write; duplicate key in table 'usercircle' 

4
Nếu tôi nhớ chính xác, khóa chính luôn luôn là một INDEX ĐỘC ĐÁO, vậy bạn có phải bỏ câu lệnh chỉ mục duy nhất không?
Mr47

1
ON DELETE NO ACTIONsẽ bỏ toàn bộ việc sử dụng khóa ngoại. Trừ khi bạn có lý do rất cụ thể để làm điều đó.
AmazingDreams

4
@AmazedDreams Tại sao? Nó vẫn thi hành tính toàn vẹn tham chiếu. Chỉ có bạn phải tự xóa con. Điều này an toàn hơn so với xóa theo tầng mà bạn có thể vô tình xóa nhiều dữ liệu bằng cách xóa một từ khóa không chính xác.
GolezTrol

1
stackoverflow.com/a/5810024/1567737 Tại sao sử dụng bí danh khi sử dụng 'bí danh' làm cho mục đích rõ ràng ngay lập tức?
AmazingDreams

@AmazedDreams Cảm ơn vì tiền boa. Tôi cũng thích cuộc tranh luận xung quanh nó - nó giúp tôi tìm hiểu về những ưu và nhược điểm.
Git-có thể

Câu trả lời:


534

Nhiều khả năng bạn đã có một ràng buộc với tên iduserhoặc idcategorytrong cơ sở dữ liệu của bạn. Chỉ cần đổi tên các ràng buộc nếu có.

Các ràng buộc phải là duy nhất cho toàn bộ cơ sở dữ liệu, không chỉ cho bảng cụ thể mà bạn đang tạo / thay đổi.

Để tìm ra nơi các ràng buộc hiện đang được sử dụng, bạn có thể sử dụng truy vấn sau:

SELECT `TABLE_SCHEMA`, `TABLE_NAME`
FROM `information_schema`.`KEY_COLUMN_USAGE`
WHERE `CONSTRAINT_NAME` IN ('iduser', 'idcategory');

15
Chính xác như bạn đã nói. Nhiều ràng buộc đã được tạo tự động với cùng tên người dùng idc Category trong phần còn lại của truy vấn CREATE - cảm ơn sự giúp đỡ của bạn!
Git-có thể

1
Tôi nghĩ rằng MySQL Workbench đã sửa lỗi này khi xuất tập lệnh tạo, nhưng đó là những gì tôi nhận được cho "Bỏ qua" trong cảnh báo về loại điều này khi tôi mở dự án.
SnowInferno

Cảm ơn, bạn đời :) Điều đó giúp tôi rất nhiều và bây giờ quy ước về khóa ngoại của tôi đã khác và tôi không thể gặp lại vấn đề này :)

Có thể xác nhận điều đó. Nhưng tôi có thể làm gì nếu ràng buộc có tên tồn tại mặc dù bảng tham chiếu đã bị hủy ?? Tôi có thể bỏ một ràng buộc từ một bảng không tồn tại không? Tôi đoán tôi nên cập nhật từ MySQL 5.6 lên MariaDB hiện tại.
Anse

3
Cảm ơn bạn vì điều này: Các ràng buộc phải là duy nhất cho toàn bộ cơ sở dữ liệu
sebasira

31

Thay đổi tên khóa ngoại trong MySQL. Bạn không thể có cùng tên khóa ngoại trong bảng cơ sở dữ liệu.

Kiểm tra tất cả các bảng của bạn và tất cả các khóa ngoại của bạn và tránh có hai khóa ngoại có cùng tên chính xác.


Đó là vấn đề trong trường hợp của tôi. Tôi sẽ không bao giờ đoán được nó và bạn đã cứu ngày của tôi. Sử dụng fk_id_1, fk_id_2, v.v., ngay bây giờ. Cảm ơn.
JackLeEmmerdeur

15

Từ hai liên kết được giải quyết thành côngquy ước đặt tên , tôi dễ dàng giải quyết vấn đề tương tự mà tôi gặp phải. tức là, đối với tên khóa ngoại, đặt dưới dạng fk _colName_ TableName . Quy ước đặt tên này không mơ hồ và cũng làm cho mọi ForeignKey trong Mô hình DB của bạn trở nên độc nhất và bạn sẽ không bao giờ gặp phải lỗi này.

Lỗi 1022: Không thể viết; khóa trùng lặp trong bảng


6

Như những người khác đã đề cập, có thể tên cho ràng buộc của bạn đã được sử dụng bởi một bảng khác trong DB của bạn . Chúng phải là duy nhất trên cơ sở dữ liệu.

Một quy ước tốt để đặt tên cho các ràng buộc khóa ngoại là:

fk_TableName_ColumnName

Để điều tra xem liệu có thể xảy ra xung đột hay không, bạn có thể liệt kê tất cả các ràng buộc được sử dụng bởi cơ sở dữ liệu của bạn với truy vấn này:

SELECT * FROM information_schema.table_constraints WHERE constraint_schema = 'YOUR_DB';

Khi tôi chạy truy vấn này, tôi phát hiện ra rằng trước đây tôi đã tạo một bản sao tạm thời của bảng và bản sao này đã sử dụng tên ràng buộc mà tôi đang cố sử dụng.


4

Tôi chỉ dành 4 giờ qua với cùng một vấn đề. Những gì tôi đã làm chỉ đơn giản là đảm bảo các ràng buộc có tên duy nhất.

Bạn có thể đổi tên các ràng buộc. Tôi đã thêm một số cho tôi để tôi có thể dễ dàng theo dõi số lần xuất hiện.

Thí dụ

Nếu một ràng buộc trong bảng được đặt tên là boy có khóa ngoại X thì ràng buộc tiếp theo với khóa ngoại X có thể được gọi là boy1

Tôi chắc chắn rằng bạn sẽ tìm ra tên tốt hơn tôi đã làm. 🙂


3

Điều này cũng có thể phát sinh liên quan đến lỗi trong các phiên bản nhất định của công cụ thay đổi lược đồ trực tuyến của Percona Toolkit. Để thay đổi một bảng lớn, pt-osc trước tiên tạo một bảng trùng lặp và sao chép tất cả các bản ghi vào đó. Trong một số trường hợp, một số phiên bản pt-osc 2.2.x sẽ cố gắng đưa ra các ràng buộc trên bảng mới cùng tên với các ràng buộc trên bảng cũ.

Một bản sửa lỗi đã được phát hành trong 2.3.0.

Xem https://bugs.launchpad.net/percona-toolkit/+orms/1498128 để biết thêm chi tiết.


1

Tôi cũng gặp phải vấn đề đó. Hãy xem tên cơ sở dữ liệu đã tồn tại trong Mysql và đổi tên cũ.


1

Tôi đã có vấn đề này khi tạo một bảng mới. Hóa ra tên Khóa ngoài tôi đã sử dụng. Đổi tên khóa đã sửa nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.