Переход от файловых систем к базам данных
Электронные картотеки и системы файлов
Чтобы понять, почему классические электронные картотеки и различные формы систем, основанных на отдельных файлах, рано или поздно становятся неудобными и вынуждают переходить к централизованной базе данных, полезно мысленно перенестись в эпоху 50–60-х годов XX века, когда появлялись первые электронно-вычислительные машины (ЭВМ).
Тогда любой расчёт или учёт данных сводился к тому, что инженеры и математики писали специальные программы, а программисты «зашивали» логику работы с информацией непосредственно внутрь этих программ. Для хранения сведений (например, списков сотрудников, сводок о заказах, научных расчётов) чаще всего заводились отдельные файлы. Если возникала потребность в дополнительном поле (скажем, увеличить длину фамилии с 20 до 25 символов), программисту приходилось:
- Модифицировать структуру этих файлов в коде.
- Придумывать программу-конвертор, которая бы преобразовала уже накопленные данные к новому формату.
- Изменять процедуры чтения, записи, поиска и т. д.
Такой подход со временем показал множество узких мест. Если разные отделы в одной организации создавали «свои» картотеки, неизбежно возникала избыточность данных: у одной машины или подразделения хранился некий старый файл (например, с устаревшим телефоном клиента), у другой — более новая версия. В итоге данные о контрагенте могли расползаться на несколько десятков копий, а их синхронизация превращалась в достаточно сложную и трудоемкую задачу.
Кроме того, файлы на разных машинах часто оказывались структурно несовместимы: где-то фамилия занимала 20 байт, а где-то 15; в одном отделе разработчики писали на одном языке программирования, а в другом — на другом, с совершенно иной системой записи данных. Чтобы собрать единый отчёт или агрегировать информацию «из нескольких мест», требовалось изобретать громоздкие способы синхронного чтения разных файлов, что становилось затруднительно и для программиста, и для самой машины.
Всё это можно назвать эволюционно понятным этапом — разработчики поначалу пытались “машинным” способом воспроизвести принцип бумажной картотеки: каждая запись в своей карточке, карточки лежат в ящиках, а чтобы найти информацию, нужно найти нужный «ящик». Но в условиях быстро растущих объёмов информации и числа пользователей такой подход начал явно буксовать. Именно тогда постепенно сформировалось убеждение, что для хранения больших массивов данных и многопользовательского доступа необходимо придумывать более гибкие и централизованные решения.
Даже сегодня существуют простые приложения или утилиты, которые работают с единственным файлом (или двумя-тремя) и не требуют полноценной СУБД. Однако как только растёт количество пользователей, появляется потребность в совместном редактировании, сложных отчётах и быстрой фильтрации — системы файлов перестают удовлетворять современные требования.
Что такое база данных и зачем она нужна
Когда объём данных стал слишком велик, а требования пользователей стали включать одновременный доступ, быстрый поиск и гибкую выборку, появился новый подход: база данных (БД). Согласно ГОСТ 34.321–96, под БД понимают совокупность взаимосвязанных данных, организованных по определённой схеме для совместного использования.
Однако, справедливым будет и более расширенное определение:
База данных (database) — это организованная совокупность совместно используемых логически связанных данных и их описаний (метаданных), относящаяся к определённой предметной области и предназначенная для удовлетворения информационных потребностей организации.
Обращаясь к сути, зачем нужна база данных:
- Снижение избыточности и предотвращение конфликтов версий. Если раньше приходилось хранить телефон клиента в десятках файлов, то теперь в централизованной БД мы ведём его только в одном месте.
- Совместный доступ. Разные пользователи могут не просто просматривать, но и одновременно обновлять сведения, не рискуя затереть изменения друг друга.
- Централизованное управление. Существует единая «точка входа» — специальная программа (СУБД), которая следит, чтобы данные оставались непротиворечивыми, и выдаёт доступ только тем, кто имеет на это право.
- Надёжность и безопасность. Благодаря механизмам резервного копирования и контроля транзакций (в более поздних моделях) база данных сможет восстанавливаться после сбоев и защищать сведения от несанкционированных действий.
Появление БД стало решающим шагом, благодаря которому человечество смогло постепенно уйти от нагромождения файловых архивов и бумажных картотек к более стройной системе хранения, где есть понятия структуры, подчинённости, связей, прав доступа и многого другого.
Эволюция моделей БД
Переход к базе данных не сразу дал идеальную концепцию хранения. В 50-х и 60-х годах появились первые промышленные ЭВМ, вычислительные мощности начали расти, а вместе с ними рос и спрос на способы организации больших объёмов данных. Можно сказать, что «спусковым крючком» к массовому развитию БД послужили грандиозные технические проекты (например, космическая программа Apollo в США), где требовалось в реальном времени обрабатывать горы информации: от расчёта траектории полёта до хранения детализации заказов, выставляемых подрядчикам.
Стандартов и согласованного понимания, как именно строить базы данных, поначалу не было, поэтому появлялись разные модели БД:
Иерархическая модель
В данной модели данные представляются в виде перевёрнутого дерева: в корне (самом верхнем уровне) лежит «главный» объект, а от него отходят ветви к подчинённым объектам, у которых, в свою очередь, могут быть свои «потомки». Это было проще, чем хаотичные файлы, поскольку достаточно очевидно — один родитель, много потомков. Так было организовано, например, хранение структур «компания → отделы → сотрудники». Однако модель слишком жёстко требовала, чтобы у каждого дочернего узла был только один родитель. Если реальная жизнь требовала иначе (связи «многие ко многим»), в иерархической структуре это становилось затруднительным.
Сетевая модель
Попытка придать данным большую гибкость: вместо деревьев используется «граф»; любая запись (узел) может иметь несколько родительских элементов. Это давало более богатые возможности, однако усложняло логику администрирования и навигации по данным. Программисту всё ещё приходилось «знать», в каких именно узлах и как связаны записи, чтобы «дойти» до нужной информации.
Реляционная модель
Принципиальный прорыв произошёл в 70-х, когда Эдгар Кодд предложил описывать данные в виде таблиц (отношений), связанных между собой с помощью общих полей (ключей). Математическая база реляционной модели (теория множеств, логика) позволила формализовать многие вопросы работы с данными. Реляционные СУБД приняли во внимание опыт предыдущих подходов и свели взаимодействие к понятным операциям: добавить запись, убрать, изменить, выбрать по условию. Были разработаны первые версии языка SQL (SEQUEL), позволяющие довольно просто «запрашивать» данные. Со временем реляционные СУБД, такие как IBM DB2, Oracle, MySQL и другие, заняли доминирующую позицию в мире.
Объектно-ориентированная модель
Когда в середине 80-х объектно-ориентированное программирование стало основой софта, стали появляться идеи хранить данные в виде объектов с методами, атрибутами и наследованием. Однако «чистые» объектные БД оказались слишком сложны в стандартизации. Наиболее удачные решения — это объектно-реляционные СУБД, где к реляционной основе добавлены механизмы, напоминающие объекты.
Слабо структурированные и документ-ориентированные БД (NoSQL)
С появлением больших интернет-проектов и сменой характера данных (часто меняющиеся, не всегда фиксированной структуры) стали набирать популярность документо-ориентированные и другие нереляционные БД, способные хранить информацию, к примеру, в формате JSON. Они отлично справляются со сколь угодно «разношерстными» документами, поддерживают горизонтальное масштабирование и высокую скорость вставки. Однако для традиционных корпоративных задач зачастую всё-таки используется классическая реляционная модель, поскольку она обладает более жёсткими и отработанными механизмами целостности.
![]() |
|---|
| Эволюция БД |
Тот факт, что реляционные базы уже несколько десятилетий занимают лидирующие позиции, не отменяет существования и развития других моделей. Потребности современного мира (социальные сети, Big Data, аналитические хранилища) расширили область применения NoSQL и гибридных СУБД, но классически в первую очередь изучаются реляционные парадигмы.
Практическое задание
Представим, что вы стажёр в небольшом интернет-магазине. Вам отдали две “выгрузки” из разных отделов:
Klienty.txt— “справочник клиентов”Zakazy.txt— “журнал заказов”
Но реальные данные редко бывают “идеальными”, поэтому в наборе данных у нас есть 6 “следов работы реальной организации” — небольших, но очень показательных:
- “Висячие заказы”: в
Zakazy.txtесть несколько строк сID_Клиента, которого нет вKlienty.txt(например, 121/130/999). Плюс есть одна строка, гдеID_Клиентазаписан как09(это тот же9, если привести поле к числу). - “Двойники клиента”: один и тот же email и/или телефон встречается у разных
ID_Клиента. - Грязь в справочниках: один и тот же город написан по-разному (“Санкт-Петербург” vs “СПб”), встречаются лишние пробелы и варианты вроде “Санкт Петербург”, “С.-Петербург”.
- “Битые типы”: несколько дат записаны не в ISO-формате (
YYYY-MM-DD), сумма может оказаться текстом (12 000), встречается отрицательная сумма, а в одном заказе отсутствуетДата_Доставки. - Несогласованные справочники значений: единично встречаются значения “Способ_Оплаты” и “Способ_Доставки”, которых нет в оговорённом списке.
- Ограничение доступа по ролям: договоримся, что “оператору” нельзя видеть, например, адрес, а “аналитику” нельзя менять статусы.
Требование: Сделайте выводы и о проделанной работе в формате мини-отчета.
Исходные данные
- Файл «Klienty.txt»
Каждая строка содержит 8 полей, разделённых точкой с запятой (;).
Формат строки:
ID_Клиента;ФИО;Телефон;Город;Адрес;Email;Дата_Регистрации;Статус
Поля:
- ID_Клиента: уникальный числовой идентификатор (1..120).
- ФИО: фамилия, имя и отчество.
- Телефон: чаще всего в условном формате
+7-9xx-xxx-xx-xx, но есть 1 строка “не по шаблону”. - Город: несколько крупных городов (повторяются), есть варианты написания и лишние пробелы.
- Адрес: абстрактная уличная запись.
- Email: в основном корректный email, но есть 1 некорректное значение и 1 пустое.
- Дата_Регистрации: в интервале примерно от 2024-05 до 2024-12, но есть 1–2 строки с другим форматом даты.
- Статус: «Обычный», «VIP» или «Заблокирован» (иногда с лишними пробелами).
Пример данных:
1;Соколов Иван Антонович;+7-996-132-13-21;Екатеринбург;ул. Сибирская, д. 95, кв. 190;sokolov.ivan1@mail.ru;2024-12-15;Обычный
2;Степанов Павел Глебович;+7-994-928-10-30;Москва;ул. Дружбы, д. 84;stepanov.pavel2@mail.ru;2024-08-16;Обычный
3;Смирнова Анастасия Антоновна;+7-959-370-15-68;Санкт Петербург;ул. Технологов, д. 44, кв. 98;smirnova.anastasiya3@mail.ru;2024-05-25;Обычный
...Полный файл доступен по ссылке.
- Файл «Zakazy.txt»
Каждая строка содержит 7 полей, разделённых точкой с запятой (;).
Формат строки:
ID_Заказа;ID_Клиента;Дата;Сумма;Способ_Оплаты;Способ_Доставки;Дата_Доставки
Поля:
- ID_Заказа: уникальный номер заказа (1..150).
- ID_Клиента: номер клиента (в основном 1..120, но есть “висячие” значения).
- Дата: дата оформления (в 2025 году), в основном ISO
YYYY-MM-DD, но есть 1–2 строки с другим форматом. - Сумма: целое число (примерно 300..25000), но есть выбросы: сумма текстом (
12 000) и отрицательная сумма. - Способ_Оплаты: чаще всего «Наличные», «Карта», «Онлайн», но есть 1 значение вне списка.
- Способ_Доставки: чаще всего «Курьер» или «Самовывоз», но есть 1 значение вне списка.
- Дата_Доставки: обычно на 1–7 дней позже даты оформления, но есть 1 пустая дата и 1–2 выброса по срокам.
Пример данных:
1;1;2025-01-20;18283;Онлайн;Самовывоз;2025-01-21
2;31;2025-02-08;4292;Наличные;Курьер;2025-02-12
3;80;2025-02-28;2358;Наличные;Самовывоз;2025-03-05
...Полный файл доступен по ссылке.
Задачи:
В процессе выполнения можете сверяться с контрольными подсказками:
Klienty.txt: 120 строк,ID_Клиента1..120.Zakazy.txt: 150 строк,ID_Заказа1..150,max(Дата)(после приведения типов) = 2025-03-31.- В
Klienty.txt: 2 “нестандартные” даты, 2 города с лишними пробелами, 1 пустой email, 1 некорректный email, 1 телефон “не по шаблону”, 1 группа дублей по email и 1 группа дублей по телефону. - В
Zakazy.txt: 2 “нестандартные” даты, 1 сумма текстом (12 000), 1 отрицательная сумма (-500), 1 “оплата вне списка”, 1 “доставка вне списка”, 1 пустаяДата_Доставки, 1 заказ сДата_ДоставкираньшеДата.
1. “Это данные или просто текст, удачно разложенный по колонкам?”
Я думаю хотя бы раз вы сталкивались с ситуацией, что дата выглядит как дата, но сортируется как строка, или сумма выглядит как число, но не суммируется. До первого отчёта кажется, что это мелочь. После первого отчёта — становится понятно, что мелочь здесь только ваше терпение.
Импортируйте Klienty и Zakazy в Excel так, чтобы это стали две нормальные таблицы (с заголовками), приведите типы (ID — число, даты — дата, сумма — число) и соберите короткий список “подозрительных” строк, где тип не распознался/сломался (например, дата как текст или пустая дата). Результат — лист DataQuality с найденными проблемными строками + краткая заметка что именно было не так.
В Excel вам помогут:
- Text Import Wizard при импорте TXT/CSV (можно сразу указать разделитель ; и типы столбцов).
- “Базовые” преобразования: DATEVALUE(), VALUE(), IFERROR().
- Для будущей корректности можно ограничить ввод дат/чисел/списков допустимых значений.
Почему в СУБД тип поля — это часть схемы, и что система выигрывает, заставляя вас определить типы заранее?
2. “Покажите заказ… но чтобы сразу было видно: кто это, откуда, и какой у него статус”
В этот момент сотрудники обычно делает первый “файловый грех”: склеивает всё в одну таблицу, потому что “так удобнее смотреть”. А через пару минут приходит второе требование: “а теперь обновите email клиента”. И вы внезапно понимаете, что email теперь живёт в трёх местах, а правду вы потеряли где-то по дороге.
Соберите “единый вид заказа” (как будто это один отчёт), где в каждой строке заказа есть: ID_Заказа, Дата, Сумма, Способ_Оплаты, Способ_Доставки, Дата_Доставки + из клиентов ФИО, Город, Email, Статус. Результат — лист UnifiedView, который обновляется при изменении исходных таблиц.
В Excel вам помогут:
- XLOOKUP для подтягивания полей по
ID_Клиента - IFNA/IFERROR + обработка #N/A как индикатора проблем (не найден клиент / “висячая” ссылка)
Почему JOIN лучше “склейки” с точки зрения актуальности данных?
3. “Бизнес не читает строки. Бизнес хочет ответы: найти, отфильтровать, посчитать”
Дальше начинается самое знакомое: “покажите крупные заказы за период”, “только VIP”, “какие доставки опоздали”, “выручка по городам”, “средний чек по статусам”. И вот тут видно, что “таблица” — это только начало. Нужен язык вопросов к данным: фильтры, условия, группировки, суммы/средние.
На основе UnifiedView (или связки двух таблиц) подготовьте три результата на листе Report:
- выборка “крупные заказы”: Сумма > 10000 за последние 5 дней данных (то есть от
max(Дата)минус 4 дня), вывестиДата, Сумма, ФИО; Подсказка для самопроверки: после приведения типовmax(Дата)должно получиться 2025-03-31 (значит “последние 5 дней” это 2025-03-27..2025-03-31). - выборка “VIP и деньги”:
Статус = VIPиСпособ_Оплаты ∈ {Онлайн, Карта}; - отчёт “сколько и на сколько”: выручка и количество заказов по городу и по статусу (можно двумя сводными/двумя блоками).
В Excel вам помогут:
- PivotTable для COUNT/SUM/AVG по городу/статусу/датам.
- SUMIFS / COUNTIFS / AVERAGEIFS для отчётов “по условиям”.
Почему правильные типы критичны для агрегатов?
4. “А что если у нас не один ‘Иванов’, а два — и оба вроде как настоящие?”
Пора затронуть тему того, что в файлах происходит постоянно: один отдел завёл клиента, второй завёл того же клиента ещё раз — и дальше вы живёте с двумя версиями реальности. У одного email старый, у другого новый. В отчёте они два разных человека. В жизни — один.
Найдите “двойников” среди клиентов минимум по двум критериям: одинаковый email и/или одинаковый телефон у разных ID_Клиента. Результат — лист Duplicates со списком подозрительных пар/групп и коротким выводом, чем это опасно для отчётов (например, “один человек считается двумя клиентами”). Если в данных есть вариативность города (“СПб” vs “Санкт-Петербург”), покажите, как она искажает группировки (до/после нормализации).
Подсказка: в исходных данных есть как минимум 1 группа дублей по email и 1 группа дублей по телефону. Чтобы уложиться по времени: нормализацию города достаточно показать на одном примере (“СПб/Санкт-Петербург”), без приведения к единому виду всех городов.
В Excel вам помогут:
- Conditional Formatting → Duplicate Values чтобы подсветить двойников.
- Data → Remove Duplicates.
- Advanced Filter → Unique records only (для выделения уникальных).
- Для нормализации “СПб/Санкт-Петербург/лишние пробелы” — TRIM() + Find/Replace.
5. А что если у нас появятся “висячие данные”?
Все мы с вами так или иначе сталкивались с ситуацией, когда какие-то данные теряют актуальность, те же ваши лабораторные с первого курса. Когда данные устаревают мы либо забываем про них, либо удаляем. Но в какой-то момент жизни (когда их можно продать следующему первому курсу) — вспоминаем о них. Переходим по ссылке, а данных то уже нет..
По логике вещей такие строки, которые их упоминают, должны исчезать, иначе возникает нарушение ссылочной целостности. Поэтому проверьте выданный выбор данных и убедитесь, точно ли там нет таких “хвостов”?
Найдите все заказы, у которых ID_Клиента не находится в таблице клиентов, и посчитайте, сколько таких заказов (и на какую сумму). Результат — лист Orphans со списком этих заказов + итоги (кол-во/сумма).
Подсказка: если ID_Клиента приведён к числу, то значение 09 должно совпасть с клиентом 9 и не считаться “висячим”.
Самопроверка: при корректно приведённом ID_Клиента должно получиться 8 “висячих” заказов на сумму 92779.
В Excel вам помогут: XLOOKUP и обрабатывать #N/A записи.
Встречались ли вы с этим в Access, когда включали обеспечение целостности связи?
6. “А теперь представьте, что структура меняется. Маркетинг попросил новое поле” (опц.)
Сегодня вам достаточно Email. Завтра скажут: “добавьте Канал_привлечения”. Послезавтра: “у клиента может быть два email”. В файловом мире это выглядит как “переделаем табличку”. А в реальности — ломаются отчёты, ломаются склейки, ломаются инструкции, ломается всё, что держалось на прежней форме данных.
Дополнительно (по желанию), добавьте в клиентов новое поле (например, Канал_привлечения) и заполните его хотя бы для 10 строк, а затем проверьте, что ваш UnifiedView и Report продолжают работать.
Если после добавления столбца что-то “поехало” (частый случай при VLOOKUP с номером столбца), зафиксируйте где именно сломалось и что пришлось поменять. Если ничего не сломалось (часто бывает при XLOOKUP), тоже напишите почему. Результат — короткий вывод на листе Notes: “что изменили”, “сломалось/не сломалось”, “почему”.
В Excel вам помогут: перевести диапазоны в Excel Table и строить формулы на structured references
7. “Нас много. И иногда всё идёт не по плану: конфликты, перетирания, ‘а у меня было иначе’” (опц.)
Один оператор меняет email, второй меняет статус. Один успел сохранить, второй сохранил позже — и “кто-то потерял правку”. В файлах это часто выглядит как бытовая трагедия: “перезалей мне актуальную версию”. В СУБД это штатный режим: конкуренция изменений решается механизмами блокировок/транзакций, а не договорённостями.
Если осталось время, попробуйте воспроизвести “конфликт редактирования” и коротко описать, что произошло.
Если Access недоступен, достаточно в 3–5 предложениях описать сценарий “потерянного обновления” и какой механизм (блокировка/изоляция/транзакционность) вы ожидаете от СУБД.
Инструменты (Access): RecordLocks / режимы блокировки записей
Если файл базы повредился — в Access есть Compact & Repair
почему многопользовательская работа — базовая функция БД? Почему “просто держать файл” быстро перестаёт быть вариантом?
8. “Кому вообще можно видеть и менять данные?” (опц.)
Пока у вас файлы — у всех обычно есть всё. Но в реальной организации это заканчивается плохо: кому-то нельзя видеть адрес, кому-то нельзя менять суммы, кому-то нельзя трогать статусы. И тут очень быстро выясняется: “скрыть столбик” — это не безопасность, это просьба быть хорошими.
В
.accdbнет полноценной user-level security как в старых.mdb, “по-взрослому” права доступа раскрываются в серверных СУБД.
Дополнительно: составьте на листе Notes “матрицу доступа” (роль → какие поля можно смотреть/менять). Например: “оператор” видит ФИО/город/статус и меняет статус, но не видит адрес; “аналитик” видит агрегаты и отчёты, но не меняет статусы/суммы.
И снова … Access
Импорт данных
- Откройте Access → Blank Database → создайте
shop.accdb. - External Data → New Data Source → From File → Text File и импортируйте
Klienty.txt(Delimited, разделитель;) в таблицуClients. Аналогично импортируйтеZakazy.txtв таблицуOrders.
Если группа совсем “нулевая” в импорте TXT, можно упростить: сначала открыть TXT в Excel, сохранить как XLSX и импортировать из Excel. Но TXT-импорт тоже штатный.
Приведение типов и ключи (самое важное для новичков)
-
Откройте
Clients→ Design View:ID_Клиентасделайте числовым (Long Integer) и назначьте Primary Key.
-
Откройте
Orders→ Design View:ID_Заказа→ Primary Key,ID_Клиента→ Long Integer,Дата,Дата_Доставки→ Date/Time,Сумма→ Number/Currency.
Без совпадения типов
Clients.ID_КлиентаиOrders.ID_КлиентаAccess не сможет нормально включить целостность связи.
Связь таблиц и целостность
- Database Tools → Relationships.
- Добавьте
ClientsиOrders. - Перетащите
Clients.ID_КлиентанаOrders.ID_Клиента. - Включите Enforce Referential Integrity (и по желанию каскадные опции).
Если целостность не включается с первого раза, это нормально: в наших данных есть “висячие заказы”, и Access заставит вас сначала их найти/исправить (или осознанно оставить связь без enforcement и зафиксировать это в Notes).
Запросы вместо “склейки”
- Create → Query Design → добавьте
ClientsиOrders. - Выберите поля как в
UnifiedView(из обеих таблиц) — это ваш аналог JOIN-отчёта.
“Найти и посчитать” по-СУБДшному
- Для выборок задавайте условия в строке Criteria (например, сумма > 10000, VIP, период дат).
- Для группировок включайте кнопку Totals (Σ) и используйте SUM/COUNT/AVG.
“Висячие” и “двойники”
- “Висячие”: запрос с LEFT JOIN и условием, что со стороны клиентов поле пустое (Is Null) — это стандартный паттерн поиска orphan-records.
- “Двойники”: запрос с группировкой по Email/Телефону и условием COUNT > 1.
Конфликт редактирования и восстановление
- Для ощущения многопользовательского режима попробуйте открыть базу с двух экземпляров Access и править одну запись; поведение регулируется RecordLocks.
