🐘 Руководство по SQL для начинающих. Часть 1: создание базы данных, таблиц и установка связей между таблицами
Пошаговая инструкция по установке, настройке и наполнению базы данных PostgreSQL с помощью pgAdmin и SQL-запросов. Когда вы изучаете новый язык, самым важным аспектом является практика. Одно дело – прочитать статью и совсем другое – применить полученную информацию. Давайте начнем с установки базы данных на компьютер. Мы будем использовать PostgreSQL (Postgres) – достаточно распространенный SQL диалект. Для этого откроем страницу загрузки, выберем операционную систему (в моем случае Windows), и запустим установку. Если вы установите пароль для вашей базы данных, постарайтесь сразу не забыть его, он нам дальше понадобится. Поскольку наша база будет локальной, можете использовать простой пароль, например: admin. pgAdmin – это графический интерфейс пользователя (GUI – graphical user interface), который упрощает взаимодействие с базой данных PostgreSQL. Перейдите на страницу загрузки, выберите вашу операционную систему и следуйте указаниям (в статье используется Postgres 14 и pgAdmin 4 v6.3.). После установки обоих компонентов открываем pgAdmin и нажимаем Теперь всё готово к созданию таблиц. Давайте создадим набор таблиц, которые моделируют школу. Нам необходимы таблицы: ученики, классы, оценки. При создании модели данных необходимо учитывать, что в одном классе может быть много учеников, а у ученика может быть много оценок (такое отношение называется «один ко многим»). Мы можем создать таблицы напрямую в pgAdmin, но вместо этого мы напишем код, который можно будет использовать в дальнейшем, например, для пересоздания таблиц. Для создания запроса, который создаст наши таблицы, нажимаем правой кнопкой мыши на postgres (пункт расположен в меню слева Начнем с создания таблицы классов ( В первой строке фрагмент Добавление Ничего нам не мешает добавить наш код в систему контроля версий. Весь код для создания базы данных из этой статьи вы можете посмотреть по ссылке. Также вы могли обратить внимание на четвертую строчку. Здесь мы определили, что колонка И в пятой строке мы определили, что поле Теперь давайте создадим таблицу учеников ( И снова мы перед созданием новой таблицы удаляем старую, если она существует, добавляем поле Мы определили, что Невозможно вставить данные, поскольку в таблице классов нет записи с id = 1 Теперь давайте добавим немного данных в таблицу классов ( Прекрасно! Теперь у нас есть записи в таблице классов, и мы можем добавить данные в таблицу учеников, а также установить нужные связи (с таблицей классов). Но что же случится, если у нас появится новый ученик, которому ещё не назначили класс? Неужели нам придется ждать, пока станет известно в каком он классе, и только после этого добавить его запись в базу данных? Конечно же, нет. Мы установили внешний ключ, и он будет блокировать запись, поскольку ссылка на несуществующий И наконец, давайте заполним таблицу успеваемости. Этот параметр, как правило, формируется из нескольких составляющих – домашние задания, участие в проектах, посещаемость и экзамены. Мы будем использовать две таблицы. Таблица заданий ( Вместо того чтобы вставлять данные вручную, давайте загрузим их с помощью CSV-файла. Вы можете скачать файл из этого репозитория или создать его самостоятельно. Имейте в виду, чтобы разрешить pgAdmin доступ к данным, вам может понадобиться расширить права доступа к папке (в моем случае – это папка Теперь давайте проверим, что мы всё сделали верно. Напишем запрос, который покажет среднюю оценку, по каждому виду заданий с группировкой по учителям. Отлично! Мы установили, настроили и наполнили базу данных. *** Итак, в этой статье мы научились: Теперь у нас всё готово, чтобы пробовать более сложные возможности SQL. Мы начнем с возможностей синтаксиса, которые, вероятно, вам еще не знакомы и которые откроют перед вами новые границы в написании SQL-запросов. Также мы разберем некоторый виды соединений таблиц ( В следующей части мы разберем:Установка
Первый шаг – установить SQL
Следующий шаг – установка pgAdmin
Add new server
. На этом шаге установится соединение с существующим сервером, именно поэтому необходимо сначала установить Postgres. Я назвал свой сервер home
и использовал пароль, указанный при установке.home
→ Databases (1)
→ postgres
и далее выбираем Query Tool
.classrooms
). Таблица будет простой: она будет содержать идентификатор id
и имя учителя – teacher.
Напишите следующий код в окне запроса (query tool
) и запустите (run
или F5
).
DROP TABLE IF EXISTS classrooms CASCADE; CREATE TABLE classrooms ( id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, teacher VARCHAR(100) );
DROP TABLE IF EXISTS classrooms
удалит таблицу classrooms
, если она уже существует. Важно учитывать, что Postgres, не позволит нам удалить таблицу, если она имеет связи с другими таблицами, поэтому, чтобы обойти это ограничение (constraint
) в конце строки добавлен оператор CASCADE
. CASCADE
– автоматически удалит или изменит строки из зависимой таблицы, при внесении изменений в главную. В нашем случае нет ничего страшного в удалении таблицы, поскольку, если мы на это пошли, значит мы будем пересоздавать всё с нуля, и остальные таблицы тоже удалятся.DROP TABLE IF EXISTS
перед CREATE TABLE
позволит нам систематизировать схему нашей базы данных и создать скрипты, которые будут очень удобны, если мы захотим внести изменения – например, добавить таблицу, изменить тип данных поля и т. д. Для этого нам просто нужно будет внести изменения в уже готовый скрипт и перезапустить его.id
является первичным ключом (primary key
), что означает следующее: в каждой записи в таблице это поле должно быть заполнено и каждое значение должно быть уникальным. Чтобы не пришлось постоянно держать в голове, какое значение id
уже было использовано, а какое – нет, мы написали GENERATED ALWAYS AS IDENTITY
, этот приём является альтернативой синтаксису последовательности (CREATE SEQUENCE
). В результате при добавлении записей в эту таблицу нам нужно будет просто добавить имя учителя.teacher
имеет тип данных VARCHAR
(строка) с максимальной длиной 100 символов. Если в будущем нам понадобится добавить в таблицу учителя с более длинным именем, нам придется либо использовать инициалы, либо изменять таблицу (alter table
).students
). Новая таблица будет содержать: уникальный идентификатор (id
), имя ученика (name
), и внешний ключ (foreign key
), который будет указывать (references
) на таблицу классов.
DROP TABLE IF EXISTS students CASCADE; CREATE TABLE students ( id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, name VARCHAR(100), classroom_id INT, CONSTRAINT fk_classrooms FOREIGN KEY(classroom_id) REFERENCES classrooms(id) );
id
, которое автоматически увеличивает своё значение и имя с типом данных VARCHAR
(строка) и максимальной длиной 100 символов. Также в эту таблицу мы добавили колонку с идентификатором класса (classroom_id
), и с седьмой по девятую строку установили, что ее значение указывает на колонку id
в таблице классов (classrooms
).classroom_id
является внешним ключом. Это означает, что мы задали правила, по которым данные будут записываться в таблицу учеников (students
). То есть Postgres на данном этапе не позволит нам вставить строку с данными в таблицу учеников (students
), в которой указан идентификатор класса (classroom_id
), не существующий в таблице classrooms
. Например: у нас в таблице классов 10 записей (id
с 1 до 10), система не даст нам вставить данные в таблицу учеников, у которых указан идентификатор класса 11 и больше.
INSERT INTO students (name, classroom_id) VALUES ('Matt', 1); /* ERROR: insert or update on table "students" violates foreign key constraint "fk_classrooms" DETAIL: Key (classroom_id)=(1) is not present in table "classrooms". SQL state: 23503 */
classrooms
). Так как мы определили, что значение в поле id
будет увеличиваться автоматически, нам нужно только добавить имена учителей.
INSERT INTO classrooms (teacher) VALUES ('Mary'), ('Jonah'); SELECT * FROM classrooms; /* id | teacher -- | ------- 1 | Mary 2 | Jonah */
INSERT INTO students (name, classroom_id) VALUES ('Adam', 1), ('Betty', 1), ('Caroline', 2); SELECT * FROM students; /* id | name | classroom_id -- | -------- | ------------ 1 | Adam | 1 2 | Betty | 1 3 | Caroline | 2 */
id
класса невозможна, но мы можем в качестве идентификатора класса (classroom_id
) передать null
. Это можно сделать двумя способами: указанием null
при записи значений, либо просто передачей только имени.
-- явно определим значение NULL INSERT INTO students (name, classroom_id) VALUES ('Dina', NULL); -- неявно определим значение NULL INSERT INTO students (name) VALUES ('Evan'); SELECT * FROM students; /* id | name | classroom_id -- | -------- | ------------ 1 | Adam | 1 2 | Betty | 1 3 | Caroline | 2 4 | Dina | [null] 5 | Evan | [null] */
assignments
), как понятно из названия, будет содержать данные о самих заданиях, и таблица оценок (grades
), в которой мы будем хранить данные о том, как ученик выполнил эти задания.
DROP TABLE IF EXISTS assignments CASCADE; DROP TABLE IF EXISTS grades CASCADE; CREATE TABLE assignments ( id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, category VARCHAR(20), name VARCHAR(200), due_date DATE, weight FLOAT ); CREATE TABLE grades ( id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, assignment_id INT, score INT, student_id INT, CONSTRAINT fk_assignments FOREIGN KEY(assignment_id) REFERENCES assignments(id), CONSTRAINT fk_students FOREIGN KEY(student_id) REFERENCES students(id) );
db_data
).
COPY assignments(category, name, due_date, weight) FROM 'C:/Users/mgsosna/Desktop/db_data/assignments.csv' DELIMITER ',' CSV HEADER; /* COPY 5 Query returned successfully in 118 msec. */ COPY grades(assignment_id, score, student_id) FROM 'C:/Users/mgsosna/Desktop/db_data/grades.csv' DELIMITER ',' CSV HEADER; /* COPY 25 Query returned successfully in 64 msec. */
SELECT c.teacher, a.category, ROUND(AVG(g.score), 1) AS avg_score FROM students AS s INNER JOIN classrooms AS c ON c.id = s.classroom_id INNER JOIN grades AS g ON s.id = g.student_id INNER JOIN assignments AS a ON a.id = g.assignment_id GROUP BY 1, 2 ORDER BY 3 DESC; /* teacher | category | avg_score ------- | --------- | --------- Jonah | project | 100.0 Jonah | homework | 94.0 Jonah | exam | 92.5 Mary | homework | 78.3 Mary | exam | 76.0 Mary | project | 69.5 */
JOIN
) и способы организации запросов в тех случаях, когда они занимают десятки или даже сотни строк.Материалы по теме
- 0 views
- 0 Comment
Свежие комментарии