За последние 24 часа нас посетили 20545 программистов и 1103 робота. Сейчас ищут 836 программистов ...

Внешние ключи - за и против

Тема в разделе "MySQL", создана пользователем SweD, 31 июл 2017.

  1. SweD

    SweD Активный пользователь

    С нами с:
    15 апр 2017
    Сообщения:
    14
    Симпатии:
    3
    Доброго времени! не буду открывать новую тему, дабы есть подобная.Вопрос в следующем, связь данных с одной таблицы со сворой.

    В наличии.
    Код (Text):
    1. CREATE TABLE `#__goods` (
    2.   `goods_id` int(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Товар id',
    3.   `goods_commonid` int(50) unsigned NOT NULL COMMENT '....',
    4.   `goods_name` varchar(150) NOT NULL COMMENT '....',
    5.   `goods_jingle` varchar(150) DEFAULT '' COMMENT '....',
    6.   `store_id` int(20) unsigned NOT NULL COMMENT 'ID магазина',
    7.   `store_name` varchar(150) NOT NULL COMMENT '....',
    8.   `gc_id` int(20) unsigned NOT NULL COMMENT '....',
    9. ..............
    10. ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='Таблица объектов' AUTO_INCREMENT=100000 ;

    Добавляю новую с синхронизацией данных с первой. а именно столбцов `store_id`,`goods_id`, необходимо чтобы данные в 2-й таблице были идентичны с данными (брались) в первой, а именно в столбцах указанных в начале предложения...


    Код (Text):
    1. CREATE TABLE `#__goods_map` (
    2.   `map_id` int(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Карта ID',
    3.   `store_id` int(20) unsigned NOT NULL COMMENT 'ID магазина',
    4.   `goods_id` int(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Товар id',
    5. ....
    6.    PRIMARY KEY (`map_id`),
    7.   KEY `store_id` (`store_id`)
    8. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='....';
    Этот вариант работает, но, значения в нем уникальны, а мне необходимо чтобы они брались с первого варианта... Дабы удаляя товар, удалялась автоматом точка на карте. Используя foreign ключ, пишу следующие 2 варианта:

    Код (Text):
    1.   PRIMARY KEY (`map_id`),
    2.   KEY `store_id` (`map_id`,`goods_id`,`store_id`)
    3. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='....';
    4.  
    5. или
    6.  
    7.   PRIMARY KEY (`map_id`),
    8.   KEY `store_id` (`store_id`,`goods_id`)
    9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='....';
    Инфа скудна, а то что есть уж не рассчитана на аудиторию вне глубокого изучения...
    Вопросы. Какой вариант более правильный? Я правильно понимаю работу ключа foreign? Удаляя данные с первой таблицы, удалятся данные и со второй? Если не правильно, прошу поправить, или дать рекомендации.
    2-е. Нужно ли писать допы в самом коде, для реализации данного функционала?
     
    #1 SweD, 31 июл 2017
    Последнее редактирование: 31 июл 2017
  2. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    я никогда не удаляю ничего, а то другие связи сыпятся тоже. Флаг держу для этого, его ставлю в больше нуля, согласно причине удаления.
    --- Добавлено ---
    и в нижнем куске кода я не вижу внешних ключей :(
     
  3. SweD

    SweD Активный пользователь

    С нами с:
    15 апр 2017
    Сообщения:
    14
    Симпатии:
    3
    разъясните пожалуйста, что значит внешний ключ, видно я не понимаю взаимосвязи нужным образом. Разве `store_id`,`goods_id` не есть ключи?
    Или надо так
    Код (Text):
    1.   PRIMARY KEY (`map_id`,`goods_id`,`store_id`)),
     
  4. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    ты сказал про foreign
    а тут primary

    primary это просто уникальный ключ
    а foreign - внешние ключи, по которым можно организовать каскадное удаление.
     
    SweD нравится это.
  5. SweD

    SweD Активный пользователь

    С нами с:
    15 апр 2017
    Сообщения:
    14
    Симпатии:
    3
    Понял вроде, Спасибо что направили в нужное русло! по идей добавить
    Код (Text):
    1.     CONSTRAINT `FK1` FOREIGN KEY (`map_id`, `store_id`, `goods_id`) REFERENCES `` ()
    Буду тестировать, на ошибках быстрее понимание приходит) Спасибо еще раз!
     
  6. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    если ты удалишь эти записи, то финансовые рассчёты не поедут?
     
  7. SweD

    SweD Активный пользователь

    С нами с:
    15 апр 2017
    Сообщения:
    14
    Симпатии:
    3
    Вроде не поехали, все нормально, но еще протестирую на всякий случай. При удалении товара (удаление данных с первой таблицы), удаляется и точка на карте. Спасибо за подсказку!
     
  8. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    если товар продали в точке на карте, и в/от этой точке деньги учли, то эту запись уже не удалить. А если ты удалишь точку, в которой это произошло, то это будет получается что событие осталось, а точки-то уже нет. =(
     
  9. SweD

    SweD Активный пользователь

    С нами с:
    15 апр 2017
    Сообщения:
    14
    Симпатии:
    3
    Там Карта идет независимо, поэтому и хочу сделать чтобы точка на карте синхронизировалась с уником товара, нет товара, нет точки, айди магазина - остается в любом случае, в силу того что фильтр товаров идет по магазину, по унику товара, по классификациям товара. Товар единичный, и даже если он будет не единичным, то пока не произведут выборку, Товар не удалится, а значит и точка не удалится. В связи с этим я хочу привязать именно к goods_id - товар, map_id, store_id работают, - было по умолчанию, но это слишком широкое поле, я хочу его сузить до точки - для товара, а не как сейчас, точка магазина. Но что-то все не выходит) Где то сидит то чего не вижу или не поиму(
     
  10. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    чего не выходит-то?
     
  11. SweD

    SweD Активный пользователь

    С нами с:
    15 апр 2017
    Сообщения:
    14
    Симпатии:
    3
    не синхронизируется goods_id. Создается товар, потом карта, но карта не берет значение goods_id у товара.
     
  12. SweD

    SweD Активный пользователь

    С нами с:
    15 апр 2017
    Сообщения:
    14
    Симпатии:
    3
    CONSTRAINT `FOREIGN KEY (``goods_id``)` FOREIGN KEY (`goods_id`) REFERENCES `*_goods` ();
    /* Ошибка SQL (1064): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CONSTRAINT `FOREIGN KEY (``goods_id``)` FOREIGN KEY (`goods_id`) REFERENCES `10r' at line 1 */
    /* mysql_thread_end, thread id #6212 */
    /* Затронуто строк: 0 Найденные строки: 0 Предупреждения: 0 Длительность 0 of 1 запрос: 0,000 sec. */ и все тут))))) Ладно, я упертый, не мытьем так катаньем)
     
  13. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    делай через pma, смотри его запросы
     
  14. retvizan

    retvizan Активный пользователь

    С нами с:
    27 дек 2013
    Сообщения:
    68
    Симпатии:
    22
    CONSTRAINT `FOREIGN KEY это не отдельный запрос, а часть оператора create table или alter table

    дополнительно см:
    -) хорошее короткое объяснение что такое внешние ключи
    -) статья про ошибки внешних ключей
     
    SweD нравится это.
  15. SweD

    SweD Активный пользователь

    С нами с:
    15 апр 2017
    Сообщения:
    14
    Симпатии:
    3
    Спасибо парням за наметки! Вот тут еще по поводу SQL Foreign Key, в дополнение к ссылкам, данными retvizan, кстати, он же подсказал как должно быть правильно, в данной ссылке представлено более подробно, для понимания внешних ключей.