LINUX.ORG.RU

SQL. Связи двух таблиц. Ошибка

 ,


0

1

На данный момент в БД я ещё мал и глуп, не видал больших *** проектов…=) В общем есть две таблицы usrs & month.

+----------+------------------------+------+-----+---------+----------------+
| Field    | Type                   | Null | Key | Default | Extra          |
+----------+------------------------+------+-----+---------+----------------+
| id       | int(11)                | NO   | PRI | NULL    | auto_increment |
| surname  | varchar(100)           | NO   |     | NULL    |                |
| name     | varchar(50)            | NO   |     | NULL    |                |
| photo    | varchar(50)            | NO   |     | NULL    |                |
| phone    | decimal(10,0) unsigned | NO   |     | NULL    |                |
| birthday | int(8) unsigned        | NO   |     | NULL    |                |
| id_month | int(11)                | NO   |     | NULL    |                |
+----------+------------------------+------+-----+---------+----------------+
+-------+------------+------+-----+---------+----------------+
| Field | Type       | Null | Key | Default | Extra          |
+-------+------------+------+-----+---------+----------------+
| id    | int(11)    | NO   | PRI | NULL    | auto_increment |
| month | varchar(8) | NO   |     | NULL    |                |
+-------+------------+------+-----+---------+----------------+

Хочу сделать связь с поля id_month таблицы usrs до таблицы month поля id.

MariaDB [test]> ALTER TABLE `usrs` ADD FOREIGN KEY (`id_month`) REFERENCES `month` (`id`);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`#sql-alter-212-6e1`, CONSTRAINT `#sql-alter-212-6e1_ibfk_1` FOREIGN KEY (`id_month`) REFERENCES `month` (`id`))

При попытке их связать вываливается ошибка «Не удается добавить или обновить дочернюю строку». ЧЯДНТ…?!?

★★

очевидно ваши данные неконсистентны, то есть у вас есть юзер, у которого поле id_month не может быть выражено ссылкой на один из существующих id из таблицы month

FishHook
()
Последнее исправление: FishHook (всего исправлений: 1)
Ответ на: комментарий от FishHook

сделайте select distinct id_month from user;

Видимо Вы имели ввиду usrs таблицу.

MariaDB [test]> select distinct id_month from usrs;
+----------+
| id_month |
+----------+
|        0 |
|        1 |
+----------+

Тип данных я учёл при создании поля. И там и там целочисленный

Shprot ★★
() автор топика
Последнее исправление: Shprot (всего исправлений: 3)

О-о-о…! Парни, парни, парни, я понял в чём косяк! У меня в id_month было 0 и 1, а автоинкремент в таблице month у меня с единицы начался. Сейчас подправил, всё связалось!

Спасибо за наводку! Премного благодарен!

Shprot ★★
() автор топика
Ответ на: комментарий от Shprot

дело не в том, какой тип данных. Вот смотрите, у вас есть таблица Месяц уже заполненная записями (или пустая, не важно, главное что она есть). У вас есть таблица Юзер уже заполненная записями. Теперь вы говорите, хочу чтобы Юзер.месяц было ссылкой на Месяц.ИД. Что должно произойти, если у вас есть юзер у которого месяц == 45, а такого ИД в таблице Месяц нет?

Сделайте select distinct id from month и сравните

FishHook
()
Ответ на: комментарий от firkax

Это ты так локализацию своего сайта с помощью базы делаешь? Странная затея.

Это этап обучения и БД, как можно заметить, именуется как test.
Вам лишь бы токсины свои выпустить на зелёных и неопытных.

Shprot ★★
() автор топика
Ответ на: комментарий от Shprot

а конвертируй на клиенте

Можно по подробнее…?

текстовые наименования месяцев (стырено из интернета)

#include <langinfo.h>
#include <locale.h>
#include <stdio.h>
int main() {
    const nl_item nl_abmons[12] = {ABMON_1, ABMON_2, ABMON_3, ABMON_4,
                                   ABMON_5, ABMON_6, ABMON_7, ABMON_8,
                                   ABMON_9, ABMON_10, ABMON_11, ABMON_12};
    const nl_item nl_months[12] = {MON_1, MON_2, MON_3, MON_4, MON_5, MON_6,
                                   MON_7, MON_8, MON_9, MON_10, MON_11, MON_12};
    int i;
    setlocale(LC_ALL, "");
    for (i = 0; i < 12; i++) {
        printf("%d\t%s\t%s\n",
                i+1, nl_langinfo(nl_abmons[i]), nl_langinfo(nl_months[i]));
    }
    return 0;
}
$ ./tm
1	янв	января
2	фев	февраля
3	мар	марта
4	апр	апреля
5	мая	мая
6	июн	июня
7	июл	июля
8	авг	августа
9	сен	сентября
10	окт	октября
11	ноя	ноября
12	дек	декабря

superuser ★★★★☆
()
Ответ на: комментарий от superuser

У него мария, а значит будет использоваться похапе:

~
❯ php -r 'echo date("F", mktime(0, 0, 0, 1, 1));'
January
~
❯ php -r 'echo date("F", mktime(0, 0, 0, 2, 1));'
February
~
❯ php -r 'echo date("F");'
November
~
❯ php -r "setlocale(LC_TIME, 'ru_RU.UTF-8'); echo strftime('%B', mktime(0, 0, 0, 1, 1));"
января
rtxtxtrx ★★
()
Последнее исправление: rtxtxtrx (всего исправлений: 1)
Ответ на: комментарий от superuser

Воу, воу… не гони лошадей. Конкретно по Си я параллельно читаю и моих компетенций на сегодня в этом ЯП хватает максимум на игру «Угадай число»…=)

Shprot ★★
() автор топика
Ответ на: комментарий от rtxtxtrx

У него мария, а значит будет использоваться похапе

Совершенно верно! Мне всегда было интересно за что люди хейтят то или иное, но либо из-за отсутствия альтернатив либо просто от нежелания переходить на что-то другое продолжают юзать «плохое».

PHP плох…? Тогда почему 80% всемирной паутины на нём…?
PHP умер…? Тогда откуда на горизонте релиз 8.4…? Мертвецы несут…?

Низкий порог вхождения отсюда и говнокод! Не спорю. Свои первые кейсы мне стыдно показывать, но надо найти время сделать код-ревью и вообще относиться к написанию кода не как к работе а как творчеству.

В принципе мне пиха зашла. Да, зелен я ещё, но тем не менее в простом саблайме (с парой тройкой пакетов из пакедж контрол) с нуля написал свой CMS-движок. На сегодняшний день, вооружившись книжками, пытаюсь совершенствоваться.

P.S> Спасибо за подсказку с месяцами. Принял к сведению.

Shprot ★★
() автор топика
Ответ на: комментарий от theNamelessOne

А зачем тебе вообще отдельная таблица для хранения месяцев?

Ну во-первых я ещё раз повторюсь, что это учебная БД. Это всё для понимания как работают связи в СУБД и JOIN в PHP, а во-вторых я считаю что приучать себя к порядку надо сразу. В будущем (допустим) база разрастётся и я буду знать, что есть отдельная таблица с месяцами.

Смоделируем ситуацию. Есть компания ООО «Рога и копыта». З/п офисным работникам дают в понедельник, а техническому персоналу в среду. В коде я сделаю выпадающий список, а в СУБД он будет ссылаться на связь с id_month

Ну или как пошутил оратор выше. Захочу я сделать 13-ую з/п. Проще будет добавить её в таблицу с месяцами по id.

Shprot ★★
() автор топика
Ответ на: комментарий от Shprot

Никак их не надо перечислять. Дату рождения хранят как Datetime, а там ее в нужном формате через встроенные функции выводишь. Фото блобом можно хранить и тд и тп. Но лучше какие-то обегченную таблицу users сделать, а данные профиля с фото куда в profiles засунуть. Я не знаю что ты проектируешь.

/// тут уникальные данные
users
--------
id
email unique
username unique
phone unique
password <-- хешированный должен быть
last_active <-- чтобы показывать что юзверь "онлайн", если в последний раз что-то делал минут 15 назад
created
updated


/// имя и тп - оно все не уникально
profiles
------------
id
user_id
first_name
last_name
birthday
small_photo
medium_photo
large_photo
...

Лучше ORM какой использовать. Оно для общего развития только интересно

rtxtxtrx ★★
()
Ответ на: комментарий от superuser

а где про диспансеризацию написано? ну с ней все логично. есть админ, который юзер, но не пациент, а пациент юзер… значит вырисовываются таблицы: users, roles (id, name, джсонина со списком действий…), user_roles (id, user_id, role_id), profiles (профили пациентов)… и куча-куча всего… Главное дробить и дробить все… чтобы не было мегатаблиц

rtxtxtrx ★★
()
Ответ на: комментарий от Shprot

З/п офисным работникам дают в понедельник, а техническому персоналу в среду. В коде я сделаю выпадающий список, а в СУБД он будет ссылаться на связь с id_month

  1. Как день недели, в который ты будешь выдавать ЗП, связан с месяцами?
  2. Столбец id_month заменяешь на month_no, который будет хранить порядковый номер месяца (1-12 или 0-11, не важно), таблицу month выпиливаешь. Названия месяцов для выпадающего списка формируешь в коде приложения на основе порядкого номера месяца, выше уже пару примеров привели (а можно ещё это прям в SQL-запросе делать). Отдельная таблица для этого не нужна.

Ну во-первых я ещё раз повторюсь, что это учебная БД. Это всё для понимания как работают связи в СУБД и JOIN в PHP, а во-вторых я считаю что приучать себя к порядку надо сразу

Это не порядок, это ты навертел лишнюю таблицу, просто чтобы она была (при этом у тебя получается бессмысленное усложнение схемы БД, кода запросов и приложения). А почему ты «для порядка» имя сотрудника не вынес в отдельную таблицу names? В это бы даже было чуть больше смысла (но так делать всё равно не нужно).

А для чего у тебя вообще месяц хранится в таблице юзеров? Не связан ли он случайно с birthday?

theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 1)
Ответ на: комментарий от theNamelessOne

А для чего у тебя вообще месяц хранится в таблице юзеров?

Старина, я бы с удовольствием сказал что за проект, но предвижу кучу критики и советов от лютых, скуэльных старожил что я не так делаю и в сравнении как правильно надо предаваться страсти с мадам на площади.

Скажу только так, что есть некий сервис, за который мне падает от юзеров копеечка. Так как юзеры, участвующие в проекте жёсткие колхозники, авторизацию для них я сделал по номеру телефона, а вместо пароля - их дата рождения, так как запомнить пароль им ужасно сложно. При авторизации (даже session_start не делал) перекидывает в их профиль, где они видят приветствие себя, свою фоточку и по какой месяц у них оплачен сервис. Для этого и сделал отдельную таблицу с месяцами

Это проект для себя и узкого круга пользователей. В данный момент учебный. В плане допилить и сделать всё красиво. Мнение каждого я учёл и от кого-то даже принял в работу.

P.S> Те, кто сейчас начнут с пеной у рта кричать про персональные данные, ребят идите на бам рельсы красить. Особых ПД там нет.

Shprot ★★
() автор топика
Последнее исправление: Shprot (всего исправлений: 1)