Теория
Все переменные хранятся в оперативной памяти, поэтому как только мы завершим работу программы, все её данные сотрутся. Если нам нужно хранить данные вне зависимости от того, запущена программа или нет, придётся использовать какое-то внешнее хранилище.
Самый простой способ - это записывать нужные нам данные файл при остановке программы и читать при запуске. Если данных много и они разнородные, то искать нужное нам значение становится очень трудоёмкой задачей.
Более того, если нет единого стандарта хранения данных, то каждому программисту пришлось бы либо разбираться в чужом способе хранения, либо писать свой.
Уже довольно давно хранилища данных стандартизированы и являются готовым решением. Основная их часть называется базами данных, хотя есть и другие.
Введение
Базы данных могут хранить свои записи либо на жёстком диске, либо в оперативной памяти. Первые нужны для надёжной работы больших приложений, а вторые чаще всего используются как "прокладка" между пользователем и базой данных на жёстком диске, чтобы не ждать, пока прочитаются данные с жёсткого диска. Самая популярная база данных, работающая в оперативной памяти, - это Redis.
Также базы данных различаются по схеме хранения. Первые базы данных были просто оцифрованными реестрами. Раньше все данные хранились в огромных книгах-реестрах, каждый лист которой был расчерчен под таблицу.
В первой колонке указывался номер записи, в последующих - сами данные. В базах данных эта колонка, однозначно определяющая запись(строку таблицы), называется id(identification number) - идентификационный номер. Правда, в современном программировании id может быть вообще любыми уникальными данными. Чаще всего вместо числа в id используется просто строка. Id ещё называется ключом. Столбцы таблицы называются полями, а строки – записями.
Табличный способ хранения данных называется SQL(Structured Query Language) - язык структурированных запросов. Самое распространённое решение - это Postgresql.
Помимо непосредственного хранения базы данных позволяют обрабатывать сложные запросы. Например, если у нас в таблице список учеников класса, то сформировав особым образом запрос, мы можем получить не только запись по её id, но и более сложные данные. Например, мы можем получить всех учеников, родившихся зимой, чьи фамилии начинаются на согласные.
Табличный способ хранения хорош для определённого круга задач. Такие задачи предполагают, что при извлечении данных вы будете чаще читать данные из конкретных таблиц, чем перемещаться между ними. Если ваша программа предполагает работу со связями, то лучше использовать noSQL решения. Самое популярное noSQL-решение - это GraphQL.
Связывание таблиц
В рамках задач егэ, нет нужды изучать непосредственно то или иное SQL-решение. Вам достаточно просто понимать, как связываются таблицы, и как по ним получить нужны вам ответ. Поэтому поясняющие примеры будут разобраны просто при помощи таблиц и комментариев к ним.
Рассмотрим простую задачу: ученики пишут работу, состоящую из вопросов, на каждый из которых необходимо дать просто ответ. Если у нас хватает времени сверить ответы с правильными и выставить оценку, то всё окей. Просто создадим таблицу вида:
Результаты | |||
---|---|---|---|
id | фамилия | Имя | Оценка |
0 | Иванов | Сергей | 4 |
1 | Сидоров | Павел | 4 |
2 | Петров | Александр | 5 |
По такой таблице можно всегда определить, какая оценка у того или иного ученика.
Но что если у нас нет возможности сразу же сверять ответы? Хотелось бы сохранять работы в отдельную таблицу, каждая запись которой будет просто хранить ответы. Тогда в таблице учеников мы можем просто указать, как найти работу того или иного ученика.
Здесь нам как раз пригодится id. Ведь у каждой записи он уникален. Тогда можно переделать нашу таблицу следующим образом:
Результаты | |||
---|---|---|---|
id | фамилия | Имя | id работы |
0 | Иванов | Сергей | 6 |
1 | Сидоров | Павел | 7 |
2 | Петров | Александр | 9 |
Ответы учеников поместим в другую таблицу.
Работы | ||||
---|---|---|---|---|
id | Задание 1 | Задание 2 | Задание 3 | Оценка |
6 | 10 | qwerty | 202 | |
7 | 11 | qwerty | 201 | |
9 | 11 | qwerty | 202 |
в поле id работы я специально указал другие значения, чтобы не путать их с id результата. Хотя в реальных базах при добавлении поле id заполняется автоматически первым свободным значением после последнего заданного. Соответственно, если бы мы в пустую базу данных добавили записи, то их id были бы 0, 1, 2 и т.д.
Обратите внимание: поле оценки пока что ни у кого не задано. Ведь идея была в том, что ответы заносятся во время сдачи работы, а оценки мы поставим после. Более того, такой способ хранения позволит передать работы на проверку стороннему человеку, который вообще не будет знать, чья это работа. В этом случае проверка будет более непредвзятой.
Работы | ||||
---|---|---|---|---|
id | Задание 1 | Задание 2 | Задание 3 | Оценка |
6 | 10 | qwerty | 202 | 4 |
7 | 11 | qwerty | 201 | 4 |
9 | 11 | qwerty | 202 | 5 |
Отношение между результатами и соответствующими работами называется Один ко многим(OneToMany).
После выставления оценок мы можем по этим двум таблицам определить, какую оценку получил тот или иной ученик
Результаты | |||
---|---|---|---|
id | фамилия | Имя | id работы |
0 | Иванов | Сергей | 6 |
1 | Сидоров | Павел | 7 |
2 | Петров | Александр | 9 |
Например, если мы хотим узнать, какую оценку получил Павел Сидоров, нам необходимо в его записи найти id работы, он равен 7 и в таблице работ найти запись с соответствующим id:
id | Задание 1 | Задание 2 | Задание 3 | Оценка |
---|---|---|---|---|
7 | 11 | qwerty | 202 | 5 |
Оценка равна 5.
Расширим задачу. Предположим, что каждый ученик может сдавать несколько работ, а оценку
надо выставить по лучшему результату. Можно было бы искать все записи с заданными именем
и фамилией, но это - неоптимальное решение. Тем более, если данных об ученике будет больше, то тогда
мы будем хранить много дублирующейся информации.
Такое отношение между результатами и соответствующими работами называется Многие ко многим(ManyToMany).
Лучше перестроить логику базы данных так, чтобы в таблице результатов указывался не ученик, а
id его записи в таблице учеников. Id учеников я тоже задам не 0, 1, 2
, а 10, 11, 12
.
Это сделано для того, чтобы избежать путаницы.
Переделаем таблицы:
Ученики | |||
---|---|---|---|
id | фамилия | Имя | Класс |
10 | Иванов | Сергей | 11 |
11 | Сидоров | Павел | 11 |
12 | Петров | Александр | 10 |
В таблицу учеников я добавил поле класс.
Таблица результатов теперь будет выглядеть
Результаты | |||
---|---|---|---|
id | id ученика | id работы | |
0 | 10 | 6 | |
1 | 11 | 7 | |
2 | 12 | 9 | |
3 | 10 | 10 |
Я добавил в таблицу результатов ещё одну запись. Она добавлен
Работы | ||||
---|---|---|---|---|
id | Задание 1 | Задание 2 | Задание 3 | Оценка |
6 | 10 | qwerty | 202 | 4 |
7 | 11 | qwerty | 202 | 4 |
9 | 11 | qwerty | 202 | 5 |
10 | 11 | qwerty | 202 | 5 |
Теперь попробуем по трём таблицам: результаты, оценки, ученики вывести фамилии всех учеников, которые получили оценку 5 по лучшему результату.
В таблице работ пятёрка стоит в записях с id=9
и id=10
.
В таблице результатов работе с id=9
соответствует запись
id | id ученика | id работы |
---|---|---|
2 | 12 | 9 |
По ней мы можем узнать id ученика и в таблице учеников найти нужного нам. Его id равен 12, это - Петров Александр
В таблице результатов работе с id=10
соответствует запись
id | id ученика | id работы |
---|---|---|
3 | 10 | 10 |
id ученика тоже равен 10, он принадлежит Иванову Сергею.
Диаграммы
Иногда связи показывают с помощью диаграмм
В рассматриваемых нами в таблицах языков и городов хранятся коды(id) страны, также в таблице городов содержится код(id) столицы.
Хотя такое проектирование баз считается порочным, потому что зависимость получается циклической, тем не менее, в ЕГЭ вы легко можете встретить построения такого рода.
Правильнее было бы создать четвёртую таблицу столиц и записать все связи между городами-столицами и странами. Но я специально привёл неправильную егешную базу данных, чтобы вы были к этому готовы.
На ответ задачи такое построение скорее всего не повлияет, потому что вопрос строится на основе анализа связей, а не работы с настоящей базой. Но знать об этом нужно.