Puncte:0

Cum să eliminați constrângerea cheii externe orfane în MySQL?

drapel in

Folosind MySQL 5.5. Am un tabel pentru care nu pot adăuga o cheie străină:

ALTER TABLE `SOURCE_TABLE` 
    ADD CONSTRAIN `ConstraintFK`
        CHEIE străină (`otherTableID`)
        REFERINȚE `OTHER_TABLE` (`id`)
        ON DELETE SET NULL
        LA UPDATE CASCADE;

MySQL returnează următoarea eroare:

Cod de eroare: 1005. Nu se poate crea tabelul „my_schema.#sql-4c0c_b6fc8ca” (errno: 121)

Uitandu-ma la AFIȚĂ STAREA MOTORULUI INNODB Eu iau:

------------------------
ULTIMA EROARE CHEIE STRĂINE
------------------------
220523 16:34:36 Eroare la crearea constrângerii cheii externe pentru tabelul `my_schema`.`#sql-4c0c_b6fc8ca`.
O constrângere de cheie externă a numelui `my_schema`.`ConstraintFK`
deja exista. (Rețineți că în interior InnoDB adaugă „nume bază de date”
în fața numelui constrângerii definite de utilizator.)
Rețineți că tabelele de sistem FOREIGN KEY ale InnoDB stochează
numele de constrângeri ca fiind insensibile la majuscule, cu caracterul
Colaţionare standard MySQL latin1_swedish_ci. daca tu
creați tabele sau baze de date ale căror nume diferă doar în
caractere, apoi coliziuni în constrângere
pot apărea nume. Soluție: numiți constrângerile dvs
explicit cu nume unice.

Desigur, nu există nicio constrângere numită ConstraintFK definită în această schemă, am verificat atât schema de informații, cât și Afișați CREATE TABLE SOURCE_TABLE ieșire. Acesta din urmă arată că indexul pentru cheia externă există, dar constrângerea cheii externe pare să nu existe:

-- sunt afișate doar informații relevante
CREAȚI TABEL `SOURCE_TABLE` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `otherTableID` int(11) DEFAULT NULL,
  CHEIE PRIMARĂ (`id`),
  CHEIE `ConstraintFK_idx` (`otherTableID`)
) ENGINE=InnoDB AUTO_INCREMENT=4089 DEFAULT CHARSET=utf8;

CREATE TABLE `OTHER_TABLE` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  CHEIE PRIMARĂ (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=58108 DEFAULT CHARSET=utf8;

Într-adevăr, dacă încerc să renunț la această constrângere:

ALTER TABLE `SOURCE_TABLE`
   DROP FOREIGN KEY `ConstraintFK`;

Eu iau:

Cod de eroare: 1025.Eroare la redenumirea lui „./my_schema/SOURCE_TABLE” în ​​„./my_schema/#sql2-4c0c-b6fc8ca” (errno: 152)

M-am uitat la sistemul de fișiere și nu văd niciun motiv pentru care redenumirea tabelului ar trebui să eșueze.

Din păcate, încercarea de a interoga schema de informații nu ajută:

SELECTAȚI * FROM information_schema.TABLE_CONSTRAINTS 
    WHERE information_schema.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = „CHEIE străină” 
    AND information_schema.TABLE_CONSTRAINTS.CONSTRAINT_NAME = 'ConstraintFK';

returnează un set gol, în timp ce:

SELECTAȚI * FROM information_schema.TABLE_CONSTRAINTS 
    WHERE information_schema.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = „CHEIE străină” 
    AND information_schema.TABLE_CONSTRAINTS.CONSTRAINT_SCHEMA = 'schema_mea';

returnează toate constrângerile cheii străine din my_schema de la care pot obține AFIȚI CREATE TABLE declarații, dar niciun semn de ConstraintFK...

Uitandu-ma la acest și acest, bănuiesc că s-a întâmplat ceva în trecut care a făcut ca acea cheie externă să fie orfană: într-adevăr, acest SOURCE_TABLE a fost redenumit în urmă cu ceva timp și sunt destul de sigur că cheia externă pe care încerc să o adaug a fost acolo în trecut. Soluția sugerată este să renunțați la schema și să o recreați dintr-un fișier dump. Mai pot încerca ceva care să nu implice renunțarea acestei scheme? Este destul de mare și timpul de nefuncționare ar fi relevant.

djdomi avatar
drapel za
Mauro Îmi pare rău pentru tine, dar dba este site-ul pentru întrebările Db. semnalați întrebarea dvs. pentru mișcare prin motivul comunității și selectați aparține unui alt site, acolo selectați dba și întrebarea dvs. va fi mutată la scurt timp după
drapel ua
Vă rugăm să furnizați `SHOW CREATE TABLE SOURCE_TABLE;` și `SHOW CREATE TABLE other_table;`
Mauro Molinari avatar
drapel in
@djdomi Sunt un pic confuz, sincer. Găsesc multe întrebări despre MySQL aici pe serverfault și chiar pe stackoverflow. Deci, de ce ar trebui să meargă întrebarea mea la dba?
Mauro Molinari avatar
drapel in
@RickJames Tocmai am adăugat rezultatul relevant pentru instrucțiunile SHOW CREATE TABLE. Dacă îndoiala a fost legată de tipurile de coloane, acestea se potrivesc.
drapel ua
`SELECT constraint_name FROM information_schema.referential_constraits WHERE constraint_schema = "my_schema";`
Puncte:0
drapel in

În cele din urmă, am fost forțat să arunc întreaga schemă și să o refac cu alt nume, apoi să renunț la schema cu numele vechi (și care conținea problema/coruptă SOURCE_TABLE).

Intr-adevar, am gasit acest raspuns de la dba.stackexchange.com care descrie o modalitate care probabil ar putea rezolva acest lucru și într-adevăr părea să funcționeze... până la un anumit punct:

  • recreați masa SOURCE_TABLE cu EXACT ACEEAȘI structură dar numele pe care îl avea înainte de redenumire; asigurați-vă că specificați și cheile străine (în caz contrar MySQL va returna eroarea 150), dar cu un nume diferit (în caz contrar, MySQL va returna eroarea 121). De asemenea, asigurați-vă că numele de index reflectă noile nume ale constrângerilor de cheie străină.Deci, în exemplul meu, tabelul recreat cu vechiul nume trebuie să aibă aceeași cheie străină (cum este descrisă mai sus), dar cu un nume diferit (să zicem ConstrFK în loc de ConstrângereFK); de asemenea, indexul trebuie denumit ConstrFK_idx (în caz contrar, veți primi din nou eroarea 121)
  • dacă toate cele de mai sus sunt îndeplinite, MySQL ar trebui să vă permită să creați tabelul cu vechiul nume
  • apoi puteți arunca tabelul tocmai creat
  • apoi întoarce-te la SOURCE_TABLE și reîncercați să creați ConstrângereFK după dorință... acum ar trebui să funcționeze

În cazul meu, însă, cu MySQL 5.5.62 (Percona Server), SGBD-ul s-a prăbușit complet în ultimul pas, la câteva clipe după ce am văzut că crearea cheii externe a avut într-adevăr succes. La repornire (după finalizarea recuperării în caz de blocare), tabelul era într-o stare inconsecventă (a făcut să se blocheze MySQL Workbench, în timp ce aplicațiile mele păreau să se plângă că SOURCE_TABLE nu a mai existat). Așa că, pentru a scăpa din acea situație teribilă, am fost într-adevăr forțat să arunc întreaga schemă (am lucrat la o replică actualizată, care avea SOURCE_TABLE încă intactă), reimportați ca schemă nouă, apoi aruncați schema cu tabelul problematic și scăpați de toată această durere de cap... Desigur, a necesitat cel puțin câteva ore de oprire...

djdomi avatar
drapel za
de aceea am spus, dba ar fi sursa ta de soluție ;)

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.