Як змінити закордонну референтну дію? (поведінка)


102

Я створив таблицю, яка містить стовпчик із іноземним ключем, встановлений на ON DELETE CASCADE(видалити дочірнє повідомлення, коли батьків буде видалено)

Якою буде команда SQL, щоб змінити це ON DELETE RESTRICT? (не може видалити батьків, якщо він має дітей)

Відповіді:


170

Старе запитання, але додайте відповідь, щоб можна було отримати допомогу

Його два етапи:

Припустимо, a table1має зовнішній ключ із назвою стовпця fk_table2_id, з ім'ям обмеженняfk_name і table2називається таблицею з ключем t2( щось подібне нижче на моїй схемі ).

   table1 [ fk_table2_id ] --> table2 [t2]

Перший крок , СРОК ДРУГОГО ЗАМОВЛЕННЯ: ( посилання )

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

обмеження сповіщення видалено, стовпець не видалено

Другий крок , ДОДАЙТЕ нове обмеження:

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

додаючи обмеження, стовпець вже є

Приклад:

У мене UserDetailsтаблиця відноситься до Usersтаблиці:

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`)
:
:

Перший крок:

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

Другий крок:

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)  

результат:

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
Чи не повинен обмеження, яке ви додали, бути НАДАЛИТИ ОГРАНИЧЕННЯ, як вимагає оригінальний запитання?
Номенон

Ем, що таке "каскад видалення" і чому це потрібно?
Lealo

3
@Noumenon RESTRICT є типовим, тому ви отримуєте це, коли не вказуєте.
Едруїд

1
@Lealo "при каскаді видалення" означає, що якщо ви видалите рядок із батьківської таблиці (Користувачі в цьому випадку), всі референтні рядки з дочірньої таблиці (UserDetails) також будуть видалені.
Едруїд

1
спасибі за зауваження "обмеження сповіщення видалено, стовпець не видалено", "додавання обмежень, стовпець вже є", здогадайтесь, що означає, що дані практично збереглися і там зміниться лише схема
Джордж Бірбіліс

21

Ви можете зробити це за один запит, якщо бажаєте змінити його ім'я:

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

Це корисно для мінімізації простоїв, якщо у вас є великий стіл.


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
допоміг мені знайти рішення ALTER TABLE table_name ADD...ON DELETE RESTRICT
Моак

3
Ні, fk_name - ім'я обмеження. Необов’язково її надати. Я не впевнений, але, можливо, ви можете отримати його за допомогою SHOW CREATE TABLE.
pascal

1
НА КАСКАДНЕ ОБМЕЖЕННЯ, ймовірно, не передбачається.
jgreep

5

Пам'ятайте, що після видалення зовнішнього ключа MySQL зберігає простий індекс у стовпці. Отже, якщо вам потрібно змінити стовпчик 'посилання', слід зробити це в 3 етапи

  • падіння оригінального ФК
  • падіння індексу (імена, як попередній fk, за допомогою drop indexпункту)
  • створити новий ФК

3

Ви можете просто використовувати один запит, щоб керувати ними всіма: 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
це буде працювати лише в тому випадку, якщо ви зміните ім'я обмеження (якщо, можливо, використовувати автоматично створене ім'я, можливо, воно буде спрацьовувати, думаю, MySQL завжди створює унікальні)
Джордж Бірбіліс,

Запит точно працює на MySQL / MariaDB. Ключовим тут є
скасування

1
синтаксис запитів "все в одному" не працював для мене з MySQL, коли явні обмежувальні імена використовуються
George Birbilis,

3

У мене було чимало змін у ФК, тому я щось написав, щоб зробити заяви для мене. Порахував, я поділюсь:

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
це не буде працювати, якщо обмеження є на декількох стовпцях. згенерований sql створить окремі обмеження для кожного стовпця
вогні

Всі мої FK були на одних колонках, тому я не думав так сильно про цю можливість, але добре подумав
DavidSM
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.