#set text(size: 1.3em)
#show link: underline
#set page(footer: context {
  if counter(page).get().first() > 1 [
    #align(center)[
      #counter(page).display("1")
    ]
  ]
})


#show raw.where(block: false): box.with(
  fill: luma(240),
  inset: (x: 3pt, y: 0pt),
  outset: (y: 3pt),
  radius: 2pt,
)

#show raw.where(block: true): block.with(
  fill: luma(240),
  inset: 10pt,
  radius: 4pt,
)
    
// title
    
#align(center)[Санкт-Петербургский национальный исследовательский университет информационных технологий, механики и оптики]
\
\
\
#align(center)[Факультет инфокоммуникационных технологий]
#align(center)[Направление подготовки 11.03.02]
\
\
#align(center)[Практическая работа №1.2]
#align(center)[Установка и первоначальная настройка субд postgresql.]
\
\
\ //#align(center)[Вариант 19]
\
\
\
\
\
\
\
#align(right)[Выполнил:]
#align(right)[Дощенников Никита Андреевич]
#align(right)[Группа: К3221]
#align(right)[Проверила:]
#align(right)[Татьяна Евгеньевна Войтюк]
\
\
#align(center)[Санкт-Петербург]
#align(center)[2025]

#pagebreak()
    
=== Цель работы: 

Изучение принципов проектирования и администрирования реляционных баз данных в среде postgresql с использованием графического интерфейса pgadmin и языка sql. Освоение создания, изменения и связи таблиц, настройки ограничений целостности, индексов и построения ER-диаграмм. Формирование практических навыков работы с объектами базы данных, добавления и проверки данных, а также документирования структуры базы данных.

=== Задачи, решаемые при выполнении работы.

- Освоить создание таблиц в базе данных с использованием графического интерфейса pgadmin и sql запросов.
- Научиться задавать ключевые параметры таблиц: первичные ключи, автоинкрементные поля, значения по умолчанию и ограничения `NOT NULL`.
- Изучить применение команды `ALTER TABLE` для изменения структуры таблицы без потери данных.
- Создать связи между таблицами (внешние ключи) как через интерфейс pgadmin, так и с помощью sql кода.
- Научиться создавать индексы для оптимизации поиска и сортировки данных.
- Освоить построение и редактирование er диаграмм для визуализации структуры базы данных.
- Научиться добавлять, изменять и проверять данные в таблицах с помощью интерфейса pgadmin и dml запросов.
- Изучить назначение и реализацию ограничений целостности.
- Научиться очищать таблицы с помощью команды `TRUNCATE` и выполнять внешние sql скрипты для заполнения и модификации базы.
- Сформировать целостное представление о создании и сопровождении базы данных на примере модели hr.

=== Исходные данные.

- субд postgresql и графическая оболочка pgadmin.
- бд hr, содержащая схемы и объекты для работы.
- схема employeesDepartments, созданная на предыдущем этапе.
- sql-скрипты, предоставленные в методических материалах:
- набор заданий, предполагающих создание таблиц employees, departments, locations и других таблиц базы данных hr.
- примерные структуры таблиц и параметры столбцов.
- методические указания по выполнению лабораторных работ и пошаговые инструкции с примерами sql команд и интерфейсных действий.

=== Выполнение работы.

===== Задание 1. Создание таблицы в графической среде pgadmin.

Я раскрыл базу hr до узла tables и выбрал опцию create:

#align(center)[#image("assets/1.png")]

И создал таблицу `EMPLOYEES`:

#align(center)[#image("assets/2.png")]

Затем я заполнил вкладку `columns` как показано на рисунке в условии: 

#align(center)[#image("assets/3.png")]

Для поля `employee_id`, я выставил следующие параметры: 

#align(center)[#image("assets/4.png")]

Для столбца `hire_date` я поставил значение по умолчанию `current_date`.

#align(center)[#image("assets/5.png")]

После этого, я сохранил таблицу.

===== Задание 2. Создание таблицы в Query Editor.

Я открыл query tool для hr и вписал туда следующий скрипт: 

```sql
CREATE TABLE "EmployeesDepartments"."DEPARTMENTS" (
    DEPARTMENT_ID integer GENERATED ALWAYS AS IDENTITY (INCREMENT 1 START 1) PRIMARY KEY NOT NULL, 
    DEPARTMENT_NAME character varying(30)[] NOT NULL,
    MANAGER_ID bigint NULL,
    LOCATION_ID integer NULL
);
```

#align(center)[#image("assets/6.png")]

Таблица появилась в object explorer:

#align(center)[#image("assets/7.png")]

Затем я создал еще одну таблицу скриптом: 

```sql
CREATE TABLE "EmployeesDepartments"."LOCATIONS"
    (LOCATION_ID smallint GENERATED ALWAYS AS IDENTITY NOT NULL,
     STREET_ADDRESS character varying(40),
     POSTAL_CODE character varying(12),
     CITY character varying(30),
     COUNTRY_ID CHAR(2)
    );
```

#align(center)[#image("assets/9.png")]

Как можно видеть, таблица была создана: 

#align(center)[#image("assets/10.png")]

===== Задание 3. Изменение таблицы. 

В querry tool я ввел следующее: 

```
ALTER TABLE "EmployeesDepartments"."LOCATIONS"
ADD STATE_PROVINCE character varying(25) NULL;
```

#align(center)[#image("assets/11.png")]

Изменил столбец CITY следующим кодом:

```
ALTER TABLE "EmployeesDepartments"."LOCATIONS"
ADD CONSTRAINT "PK_LokationId" PRIMARY KEY (LOCATION_ID);
```

#align(center)[#image("assets/12.png")]

Таблица locations:

#align(center)[#image("assets/13.png")]

Затем я прописал текст скрипта `script1_create.sql`:

#align(center)[#image("assets/14.png")]

#align(center)[#image("assets/15.png")]

===== Задание 4. Создание отношения графическим интерфейсом pgadmin.

Я нажал ПКМ по таблице EmployeesDepartments.LOCATIONS и выбрал меню создания внешнего ключа: 

#align(center)[#image("assets/16.png")]

Затем я ввел задание название отношения: 

#align(center)[#image("assets/17.png")]

После, я добавил столбец кнопкой add:

#align(center)[#image("assets/18.png")]

Вкладка sql:

#align(center)[#image("assets/19.png")]

Ограничения locations: 

#align(center)[#image("assets/20.png")]

Затем я создал отношение с помощью ddl оператора alter table:

```sql 
ALTER TABLE "Countries"."COUNTRIES"
ADD CONSTRAINT "COUNTR_REG_ID_FK1" FOREIGN KEY ("REGION_ID")
REFERENCES "Countries"."REGIONS" ("REGION_ID");
```

#align(center)[#image("assets/21.png")]

===== Задание 5. Создания индекса с помощью графического интерфейса pgadmin.

В таблице EmployeesDepartments.LOCATIONS, я выбрал раздел меню для создания индекса: 

#align(center)[#image("assets/22.png")]

Я в диалоге создания индекса я передал следующие параметры: 

#align(center)[#image("assets/23.png")]

#align(center)[#image("assets/24.png")]

#align(center)[#image("assets/25.png")]

sql:

#align(center)[#image("assets/26.png")]

===== Задание 6. Построение диаграмм базы данных.

Для создания диаграммы я нажал ПКМ на узел базы данных и выбрал параметр "ERD For Database":

#align(center)[#image("assets/27.png")]

Затем я скорректировал вид своей диаграммы в соответствии с условием: 
#align(center)[#image("assets/28.png")]

Я экспортировал снимок диаграммы, нажав на соответствующую кнопку. Результат: 

#align(center)[#image("assets/29.png")]

Сохранил проект диаграммы: 

#align(center)[#image("assets/30.png")]

===== Задание 7. Добавление данных в таблицу.

Я раскрыл меню для генерирования скрипта по вставке данных в таблицу Countries.CURRENCIES:

#align(center)[#image("assets/31.png")]

Затем я добавил следующий код в скрипт: 

```sql
INSERT INTO "Countries"."CURRENCIES"("COMMENTS", "CURRENCY_NAME", "CURRENCY_CODE")
VALUES('EuroZone', 'Euro', 'EUR');
```

#align(center)[#image("assets/32.png")]

После запуска скрипта проверил при помощи:

```sql
select * from "Countries"."CURRENCIES";
```

#align(center)[#image("assets/33.png")]

В столбце EMPLOYEE_ID я заменил identity с always на by default.

#align(center)[#image("assets/34.png")]

Затем при помощи графического интерфейса pgadmin, я добавил запись в таблицу "EmployeesDepartments"."EMPLOYEES":

#align(center)[#image("assets/35.png")]

#align(center)[#image("assets/36.png")]

Затем я добавил строку и сохранил данные: 

#align(center)[#image("assets/37.png")]
#align(center)[#image("assets/38.png")]
#align(center)[#image("assets/39.png")]

Затем, в querry tool я ввел следующий код: 

```sql
INSERT INTO "EmployeesDepartments"."EMPLOYEES"("FIRST_NAME", "LAST_NAME", "EMAIL", "PHONE_NUMBER", "JOB_ID", "SALARY", "COMMISSION_PCT", "MANAGER_ID", "DEPARTMENT_ID")
VALUES(2, 'Steven', 'King', 'SKING', '515.123.4567', 'AD_PRES', 24000, null, null, 90);
```

#align(center)[#image("assets/40.png")]

Проверим: 

```sql
SELECT * FROM "EmployeesDepartments"."EMPLOYEES";
```

#align(center)[#image("assets/41.png")]


===== Задание 8. Ограничения для столбцов.

Я добавил ограничения к таблицам "Countries"."SPOKEN_LANGUAGES" и "EmployeesDepartments"."EMPLOYEES" при помощи следующего кода: 

```sql
ALTER TABLE "Countries"."SPOKEN_LANGUAGES"
ADD CONSTRAINT "CTRY_NUM_FK1" FOREIGN KEY ("COUNTRY_ID")
REFERENCES "Countries"."COUNTRIES" ("COUNTRY_ID");
```

#align(center)[#image("assets/42.png")]
#align(center)[#image("assets/43.png")]

и 

```sql
ALTER TABLE "EmployeesDepartments"."EMPLOYEES"
ADD CONSTRAINT "EMP_SALARY_MIN"
CHECK ("SALARY" > 0);
```

#align(center)[#image("assets/44.png")]
#align(center)[#image("assets/45.png")]

Затем я добавил еще одно ограничение для таблицы JOB_HISTORY. Для этого в свойствах таблицы в разделе constraints добавил check c условием, что "END_DATE" > "START_DATE":

#align(center)[#image("assets/46.png")]
#align(center)[#image("assets/47.png")]

Я включил это ограничение выключив соответствующую опцию: 

#align(center)[#image("assets/48.png")]
#align(center)[#image("assets/49.png")]

Также я проверил работоспособность ограничения: 

```sql
INSERT INTO "EmployeesDepartments"."JOB_HISTORY"
("EMPLOYEE_ID", "START_DATE", "END_DATE", "JOB_ID", "DEPARTMENT_ID")
VALUES(200, '06-17-1993', '09-17-1987', 'AD_ASST', 90);
```

#align(center)[#image("assets/50.png")]

и 

```sql
INSERT INTO "EmployeesDepartments"."JOB_HISTORY"
("EMPLOYEE_ID", "START_DATE", "END_DATE", "JOB_ID", "DEPARTMENT_ID")
VALUES(200, '06-17-1981', '06-17-1993', 'AD_ASST', 90);
```

#align(center)[#image("assets/51.png")]

===== Задание 9. Очистка таблиц и завершение создания БД HR.

Я произвел очистку таблицы EMPLOYEES с помощью DDL команды `TRUNCATE`:

```sql
TRUNCATE "EmployeesDepartments"."EMPLOYEES";
```

#align(center)[#image("assets/52.png")]

Также я очистил JOB_HISTORY и CURRENCIES:

```sql
TRUNCATE "EmployeesDepartments"."JOB_HISTORY";
```

#align(center)[#image("assets/53.png")]

и

```sql
TRUNCATE "Countries"."CURRENCIES";
```

#align(center)[#image("assets/54.png")]

После очистки я выполнил код из файла `script2_alter.sql`:

#align(center)[#image("assets/55.png")]

И для добавления данных, я выполнил скрипт `script3_insert.sql`:

#align(center)[#image("assets/56.png")]

Результат: 

#align(center)[#image("assets/57.png")]

=== Выводы.

В ходе работы были поставлены цели изучить принципы проектирования и администрирования реляционных баз данных в postgresql, освоить создание таблиц, настройку ключей и ограничений, добавление и проверку данных, а также построение er диаграмм.

Что должны были достичь:

- Создать таблицы с корректной структурой и типами данных.
- Настроить первичные и внешние ключи, ограничения `NOT NULL` и `CHECK`.
- Добавить тестовые данные через pgadmin и sql запросы.
- Создать индексы и визуализировать структуру базы данных через er диаграмму.

Что фактически достигнуто:

- Все требуемые таблицы созданы.
- Настроены первичные и внешние ключи, значения по умолчанию и автоинкрементные поля.
- Добавлены данные, проверены ограничения целостности.
- Построена и сохранена er диаграмма базы.

Трудности и решения:

- Появлялись ошибки дублирования ключей при вставке данных, решено изменением генерации `IDENTITY` с `ALWAYS` на `BY DEFAULT`.
- Нарушение внешнего ключа при добавлении записей решалось последовательным заполнением родительских таблиц перед зависимыми.
- Ошибки при создании ограничений и индексов устранялись проверкой существующих объектов и корректировкой sql запросов.

Работа позволила закрепить навыки создания и администрирования баз данных в postgresql, понять логику ограничений и связей между таблицами, а также научиться эффективно добавлять и проверять данные с соблюдением целостности базы. Все задачи лабораторной выполнены с учетом практических рекомендаций и ошибок, которые возникали в процессе работы.

