MYSQL — Не удается обновить родительскую строку: сбой ограничения внешнего ключа

#mysql #sql #foreign-keys

#mysql #sql #внешние ключи

Вопрос:

db-ссылка на скрипку

ЗАПРОС СХЕМЫ

 -- GRAPH INFO TABLE--------------------------------------------------------------

CREATE TABLE GRAPH
(
    graph_id         CHAR(32)       NOT NULL   PRIMARY KEY,
    name             VARCHAR(1024)  NOT NULL
);

INSERT INTO GRAPH set graph_id = MD5('graph1'),
                      name = 'graph1';
                               
INSERT INTO GRAPH set graph_id = MD5('graph2'),
                      name = 'graph2';
                      
INSERT INTO GRAPH set graph_id = MD5('graph3'),
                      name = 'graph3';
                      
-- FIELD INFO TABLE--------------------------------------------------------------

CREATE TABLE FIELD_TEST
(
    field_id    CHAR(50)        NOT NULL   PRIMARY KEY,
    name        VARCHAR(500)    NOT NULL
);

INSERT INTO FIELD_TEST set field_id = MD5('field1'),
                           name = 'field1';
                               
INSERT INTO FIELD_TEST set field_id = MD5('field2'),
                           name = 'field2';
                      
INSERT INTO FIELD_TEST set field_id = MD5('field3'),
                           name = 'field3';
                           
-- GRAPH FIELD RELATION TABLE-----------------------------------------------------

CREATE TABLE GRAPH_FIELD_INFO_TEST
(
    field_id    CHAR(32)                                   NOT NULL,
    graph_id    CHAR(32)                                   NOT NULL,
    PRIMARY KEY (graph_id, field_id),
    CONSTRAINT GRAPH_FIELD_INFO_TEST_FIELD_field_id_fk
        FOREIGN KEY (field_id) REFERENCES FIELD_TEST (field_id)
            ON UPDATE CASCADE ON DELETE CASCADE,
    CONSTRAINT GRAPH_FIELD_INFO_TEST_GRAPH_STORAGE_graph_id_fk
        FOREIGN KEY (graph_id) REFERENCES GRAPH (graph_id)
            ON UPDATE CASCADE ON DELETE CASCADE
);

INSERT INTO GRAPH_FIELD_INFO_TEST set field_id = MD5('field1'),
                                      graph_id = MD5('graph1');
                                      
INSERT INTO GRAPH_FIELD_INFO_TEST set field_id = MD5('field2'),
                                      graph_id = MD5('graph2');     
                                      
INSERT INTO GRAPH_FIELD_INFO_TEST set field_id = MD5('field3'),
                                      graph_id = MD5('graph3');                                      
 

ЗАПРОС НА ОБНОВЛЕНИЕ

 UPDATE FIELD_TEST
SET name     = 'new field1',
    field_id = MD5('new field1')
WHERE field_id = MD5('field1');
 

ОШИБКА

 Query Error: Error: ER_ROW_IS_REFERENCED_2: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`GRAPH_FIELD_INFO_TEST`, CONSTRAINT `GRAPH_FIELD_INFO_TEST_FIELD_field_id_fk` FOREIGN KEY (`field_id`) REFERENCES `FIELD_TEST` (`field_id`) ON DELETE CASCADE ON UPDATE CASCADE)
 

Если я изменю идентификатор FIELD_TEST,

Чтобы изменить идентификатор GRAPH_FIELD_INFO_TEST, ссылающийся на идентификатор FIELD_TEST,

Я установил его как каскад в GRAPH_FIELD_INFO_TEST.

Однако это не удается из-за следующей ошибки.

Если я изменю идентификатор GRAPH, он будет работать нормально,

но это не работает должным образом, только если изменен идентификатор FIELD_TEST .

Могу ли я узнать причину ошибки?

Ответ №1:

field_id В вашей FIELD_TEST таблице это a CHAR(50) , но в вашей GRAPH_FIELD_INFO_TEST таблице это a CHAR(32) .

CHAR это тип фиксированной длины, поэтому при обновлении field_id в FIELD_TEST таблице система пытается также обновить ссылочный столбец с помощью a CHAR(50) , который, конечно, терпит неудачу (хотя фактическое значение составляет всего 32 символа). Таким образом, ошибка. Измените field_id столбец, чтобы он имел одинаковую длину во всех таблицах… Как отмечено в вашей db-скрипке, это работает для GRAPH... отношений, потому что поля во всех таблицах имеют одинаковую длину.

Да, это работает, когда вы вставляете данные, потому 'foobar' = 'foobar' что даже когда один из них поступает из CHAR(50) столбца, а другой — из CHAR(32) столбца. Поэтому, когда вы вставляете в свою дочернюю таблицу, он может найти соответствующий ключ в родительской таблице. Но он не может выполнить каскадное обновление, когда родительский ключ длиннее дочернего.

Комментарии:

1. Я не могу поверить, что не вижу этого. Большое спасибо!