Làm cách nào để thay đổi hành động tham chiếu khóa ngoại? (hành vi)


102

Tôi đã thiết lập một bảng chứa một cột có khóa ngoại, được đặt thành ON DELETE CASCADE(xóa con khi cha mẹ bị xóa)

Lệnh SQL sẽ thay đổi điều này thành ON DELETE RESTRICTgì? (không thể xóa cha mẹ nếu nó có con)

Câu trả lời:


170

Câu hỏi cũ nhưng thêm câu trả lời để một người có thể nhận được trợ giúp

Quy trình hai bước của nó:

Giả sử, a table1có một khóa ngoại với tên cột fk_table2_id, với tên ràng buộcfk_nametable2được gọi là bảng có khóa t2( giống như dưới đây trong sơ đồ của tôi ).

   table1 [ fk_table2_id ] --> table2 [t2]

Bước đầu tiên , DROP CONSTRAINT cũ: ( tham khảo )

ALTER TABLE `table1` 
DROP FOREIGN KEY `fk_name`;  

thông báo ràng buộc bị xóa, cột không bị xóa

Bước thứ hai , THÊM CONSTRAINT mới:

ALTER TABLE `table1`  
ADD CONSTRAINT `fk_name` 
    FOREIGN KEY (`fk_table2_id`) REFERENCES `table2` (`t2`) ON DELETE CASCADE;  

thêm ràng buộc, cột đã ở đó

Thí dụ:

Tôi có một UserDetailsbảng tham chiếu đến Usersbảng:

mysql> SHOW CREATE TABLE UserDetails;
:
:
 `User_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`Detail_id`),
  KEY `FK_User_id` (`User_id`),
  CONSTRAINT `FK_User_id` FOREIGN KEY (`User_id`) REFERENCES `Users` (`User_id`)
:
:

Bước đầu tiên:

mysql> ALTER TABLE `UserDetails` DROP FOREIGN KEY `FK_User_id`;
Query OK, 1 row affected (0.07 sec)  

Bước thứ hai:

mysql> ALTER TABLE `UserDetails` ADD CONSTRAINT `FK_User_id` 
    -> FOREIGN KEY (`User_id`) REFERENCES `Users` (`User_id`) ON DELETE CASCADE;
Query OK, 1 row affected (0.02 sec)  

kết quả:

mysql> SHOW CREATE TABLE UserDetails;
:
:
`User_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`Detail_id`),
  KEY `FK_User_id` (`User_id`),
  CONSTRAINT `FK_User_id` FOREIGN KEY (`User_id`) REFERENCES 
                                       `Users` (`User_id`) ON DELETE CASCADE
:

2
Không phải ràng buộc bạn thêm phải là ON DELETE RESTRICT như yêu cầu của câu hỏi ban đầu?
Noumenon

Ehm, "trên xóa thác" là gì và tại sao điều đó là cần thiết?
Lealo

3
@Noumenon RESTRICT là mặc định, vì vậy bạn sẽ nhận được điều đó khi không chỉ định.
edruid

1
@Lealo "trên dòng thác xóa" có nghĩa là nếu bạn xóa một hàng khỏi bảng mẹ (Người dùng trong trường hợp này) thì tất cả các hàng tham chiếu từ bảng con (UserDetails) cũng bị xóa.
edruid

1
cảm ơn cho ghi chú "thông báo hạn chế này sẽ bị xóa, cột sẽ không bị xóa", "thêm khó khăn, cột là đã có", đoán rằng phương tiện dữ liệu được thực tế bảo quản và chỉ có thay đổi giản đồ có
George Birbilis

21

Bạn có thể thực hiện điều này trong một truy vấn nếu bạn muốn đổi tên của nó:

ALTER TABLE table_name
  DROP FOREIGN KEY `fk_name`,
  ADD CONSTRAINT `fk_name2` FOREIGN KEY (`remote_id`)
    REFERENCES `other_table` (`id`)
    ON DELETE CASCADE;

Điều này rất hữu ích để giảm thiểu thời gian chết nếu bạn có một bàn lớn.


12
ALTER TABLE DROP FOREIGN KEY fk_name;
ALTER TABLE ADD FOREIGN KEY fk_name(fk_cols)
            REFERENCES tbl_name(pk_names) ON DELETE RESTRICT;

2
giúp tôi tìm ra giải pháp ALTER TABLE table_name ADD...ON DELETE RESTRICT
Moak

3
Không, fk_name là tên ràng buộc. Nó là tùy chọn để cung cấp một. Tôi không chắc nhưng có thể bạn có thể lấy nó bằng cách sử dụng SHOW CREATE TABLE.
pascal

1
HẠN CHẾ VỀ CASCADE có lẽ không phải là dự định.
jgreep

5

Hãy nhớ rằng MySQL giữ một chỉ mục đơn giản trên một cột sau khi xóa khóa ngoại. Vì vậy, nếu bạn cần thay đổi cột 'tham chiếu', bạn nên thực hiện theo 3 bước

  • thả FK gốc
  • thả một chỉ mục (đặt tên như fk trước đó, sử dụng drop indexmệnh đề)
  • tạo FK mới

3

Bạn có thể chỉ cần sử dụng một truy vấn để thống trị tất cả: ALTER TABLE products DROP FOREIGN KEY oldConstraintName, ADD FOREIGN KEY (product_id, category_id) REFERENCES externalTableName (foreign_key_name, another_one_makes_composite_key) ON DELETE CASCADE ON UPDATE CASCADE


1
điều này sẽ chỉ làm việc nếu bạn thay đổi tên hạn chế (nếu sử dụng một cái tên tự động tạo ra có lẽ nó sẽ làm việc, đoán MySQL luôn tạo ra những độc đáo)
George Birbilis

Truy vấn hoạt động chắc chắn trên MySQL / MariaDB. Chìa khóa ở đây là để thả chế cũ bởi nó tên, hiện đang được thực hiện tại dòng 2.
stamster

1
all-in-one cú pháp truy vấn đã không làm việc cho tôi với MySQL khi tên hạn chế rõ ràng nơi sử dụng
George Birbilis

3

Tôi có một loạt các FK để thay đổi, vì vậy tôi đã viết một cái gì đó để đưa ra các tuyên bố cho tôi. Hình tôi sẽ chia sẻ:

SELECT

CONCAT('ALTER TABLE `' ,rc.TABLE_NAME,
    '` DROP FOREIGN KEY `' ,rc.CONSTRAINT_NAME,'`;')
, CONCAT('ALTER TABLE `' ,rc.TABLE_NAME,
    '` ADD CONSTRAINT `' ,rc.CONSTRAINT_NAME ,'` FOREIGN KEY (`',kcu.COLUMN_NAME,
    '`) REFERENCES `',kcu.REFERENCED_TABLE_NAME,'` (`',kcu.REFERENCED_COLUMN_NAME,'`) ON DELETE CASCADE;')

FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
LEFT OUTER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
    ON kcu.TABLE_SCHEMA = rc.CONSTRAINT_SCHEMA
    AND kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
WHERE DELETE_RULE = 'NO ACTION'
AND rc.CONSTRAINT_SCHEMA = 'foo'

1
điều này sẽ không hoạt động nếu một ràng buộc nằm trên nhiều cột. sql tạo ra sẽ tạo ra những hạn chế riêng cho từng cột
sáng

Tất cả các FKS của tôi là trên các cột duy nhất, vì vậy tôi đã không suy nghĩ nhiều về khả năng này, nhưng tốt nghĩ
DavidSM
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.