Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 88abef6d04 | |||
| d0c27b2553 | |||
| 5dce1d3f9a | |||
| 99b5d44362 | |||
| bd1520fd02 |
@@ -4,10 +4,6 @@ create or replace function convert_to_initials(
|
||||
p_patronymic varchar
|
||||
) returns varchar as $$
|
||||
begin
|
||||
if p_name is null or p_name = '' or p_surname is null or p_surname = '' then
|
||||
return '';
|
||||
end if;
|
||||
|
||||
if p_patronymic is null or p_patronymic = '' then
|
||||
return concat(substring(p_name from 1 for 1), '. ', p_surname);
|
||||
end if;
|
||||
|
||||
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.0 KiB |
@@ -191,7 +191,7 @@
|
||||
\label{fig:view}
|
||||
\end{figure}
|
||||
|
||||
\begin{lstlisting}[mathescape=true, language=SQL, caption={Запрос для создания представления \texttt{sportsman\_requests\_series\_count}.}, label={lst:view1}]
|
||||
\begin{lstlisting}[language=SQL, caption={Запрос для создания представления \texttt{sportsman\_requests\_series\_count}.}, label={lst:view1}]
|
||||
create view
|
||||
sportsman_requests_series_count as
|
||||
select
|
||||
@@ -210,7 +210,7 @@
|
||||
|
||||
Также был составлен пример запроса, в котором используется представление \texttt{sportsman\_requests\_series\_count}, его код представлен на Рис.~\ref{lst:view2}. В этом запросе выбираются 10 самых активных с точки зрения участия в соревнованиях спортсменов из клуба <<ЛК Парадокс Лучника>>. К исходному представлению также добавляются дополнительные столбцы с данными спортсмена из таблицы \texttt{sportsman}. Результат выполнения этого запроса представлен на Рис.~\ref{fig:view_query}.
|
||||
|
||||
\begin{lstlisting}[mathescape=true, language=SQL, caption={Код примера запроса, в котором используется представление \texttt{sportsman\_requests\_series\_count}.}, label={lst:view2}]
|
||||
\begin{lstlisting}[language=SQL, caption={Код примера запроса, в котором используется представление \texttt{sportsman\_requests\_series\_count}.}, label={lst:view2}]
|
||||
select
|
||||
srsc.id_sportsman,
|
||||
s.name,
|
||||
@@ -252,7 +252,7 @@
|
||||
|
||||
Для выполнения поставленной задачи, была создана отдельная таблица для сохранения статистики -- \texttt{judge\_statistics}. Код запроса для её создания представлен на Рис.~\ref{lst:trigger-table}.
|
||||
|
||||
\begin{lstlisting}[mathescape=true, language=SQL, caption={Код запроса для создания таблицы \texttt{judge\_statistics}.}, label={lst:trigger-table}]
|
||||
\begin{lstlisting}[language=SQL, caption={Код запроса для создания таблицы \texttt{judge\_statistics}.}, label={lst:trigger-table}]
|
||||
create table judge_statistics (
|
||||
id_judge integer primary key,
|
||||
competition_count integer not null default 0,
|
||||
@@ -269,7 +269,7 @@
|
||||
\item \textbf{Действие:} добавляет нового судью в \texttt{judge\_statistics}.
|
||||
\item \textbf{Код:} листинг~\ref{lst:trigger1}.
|
||||
\end{itemize}
|
||||
\begin{lstlisting}[mathescape=true, language=SQL, caption={Код запроса для создания триггера \texttt{after\_judge\_insert} и функции \texttt{update\_statistics\_on\_judge\_insert}.}, label={lst:trigger1}]
|
||||
\begin{lstlisting}[language=SQL, caption={Код запроса для создания триггера \texttt{after\_judge\_insert} и функции \texttt{update\_statistics\_on\_judge\_insert}.}, label={lst:trigger1}]
|
||||
create or replace function update_statistics_on_judge_insert()
|
||||
returns trigger as $$
|
||||
begin
|
||||
@@ -290,7 +290,7 @@ execute function update_statistics_on_judge_insert();
|
||||
\item \textbf{Действие:} удаляет судей из \texttt{judge\_statistics}.
|
||||
\item \textbf{Код:} листинг~\ref{lst:trigger2}.
|
||||
\end{itemize}
|
||||
\begin{lstlisting}[mathescape=true, language=SQL, caption={Код запроса для создания триггера \texttt{after\_judge\_delete} и функции \texttt{update\_statistics\_on\_judge\_delete}.}, label={lst:trigger2}]
|
||||
\begin{lstlisting}[language=SQL, caption={Код запроса для создания триггера \texttt{after\_judge\_delete} и функции \texttt{update\_statistics\_on\_judge\_delete}.}, label={lst:trigger2}]
|
||||
create or replace function update_statistics_on_judge_delete()
|
||||
returns trigger as $$
|
||||
begin
|
||||
@@ -310,7 +310,7 @@ execute function update_statistics_on_judge_delete();
|
||||
\item \textbf{Действие:} увеличивает на единицу счётчик с количеством соревнований \\ в \texttt{judge\_statistics} для судьи, от имени которого была добавлена заявка.
|
||||
\item \textbf{Код:} листинг~\ref{lst:trigger3}.
|
||||
\end{itemize}
|
||||
\begin{lstlisting}[mathescape=true, language=SQL, caption={Код запроса для создания триггера \texttt{after\_judge\_request\_insert} и функции \texttt{update\_statistics\_on\_judge\_request\_insert}.}, label={lst:trigger3}]
|
||||
\begin{lstlisting}[language=SQL, caption={Код запроса для создания триггера \texttt{after\_judge\_request\_insert} и функции \texttt{update\_statistics\_on\_judge\_request\_insert}.}, label={lst:trigger3}]
|
||||
create or replace function update_statistics_on_judge_request_insert()
|
||||
returns trigger as $$
|
||||
begin
|
||||
@@ -332,7 +332,7 @@ execute function update_statistics_on_judge_request_insert();
|
||||
\item \textbf{Действие:} уменьшает на единицу счётчик с количеством соревнований \\ в \texttt{judge\_statistics} для судьи, от имени которого была добавлена заявка.
|
||||
\item \textbf{Код:} листинг~\ref{lst:trigger4}.
|
||||
\end{itemize}
|
||||
\begin{lstlisting}[mathescape=true, language=SQL, caption={Код запроса для создания триггера \texttt{after\_judge\_request\_delete} и функции \texttt{update\_statistics\_on\_judge\_request\_delete}.}, label={lst:trigger4}]
|
||||
\begin{lstlisting}[language=SQL, caption={Код запроса для создания триггера \texttt{after\_judge\_request\_delete} и функции \texttt{update\_statistics\_on\_judge\_request\_delete}.}, label={lst:trigger4}]
|
||||
create or replace function update_statistics_on_judge_request_delete()
|
||||
returns trigger as $$
|
||||
begin
|
||||
@@ -354,7 +354,7 @@ execute function update_statistics_on_judge_request_delete();
|
||||
\item \textbf{Действие:} уменьшает на единицу счётчик с количеством соревнований для \\ в \texttt{judge\_statistics} для судьи, от имени которого была добавлена заявка.
|
||||
\item \textbf{Код:} листинг~\ref{lst:trigger5}.
|
||||
\end{itemize}
|
||||
\begin{lstlisting}[mathescape=true, language=SQL, caption={Код запроса для создания триггера \texttt{after\_judge\_request\_update} и функции \texttt{update\_statistics\_on\_judge\_request\_update}.}, label={lst:trigger5}]
|
||||
\begin{lstlisting}[language=SQL, caption={Код запроса для создания триггера \texttt{after\_judge\_request\_update} и функции \texttt{update\_statistics\_on\_judge\_request\_update}.}, label={lst:trigger5}]
|
||||
create or replace function update_statistics_on_judge_request_update()
|
||||
returns trigger as $$
|
||||
begin
|
||||
@@ -398,7 +398,7 @@ execute function update_statistics_on_judge_request_update();
|
||||
|
||||
Примеры различных операций от имён этих пользователей вместе с реакцией СУБД демонстрируются в таблице~\ref{tbl:users}.
|
||||
|
||||
\begin{lstlisting}[mathescape=true, caption={Код запросов для создания пользователей и выдачи им определённых прав.}, label={lst:users}]
|
||||
\begin{lstlisting}[caption={Код запросов для создания пользователей и выдачи им определённых прав.}, label={lst:users}]
|
||||
create user readonly_user with password '123';
|
||||
grant usage on schema public to readonly_user;
|
||||
grant select on sportsman_requests_series_count to readonly_user;
|
||||
@@ -567,22 +567,18 @@ grant usage, select on sequence shot_series_id_shot_series_seq to edit_user;
|
||||
\subsection{Работа 4: Создание функций и процедур}
|
||||
\textbf{Задача:} Создать функцию и использовать её в запросе. Создать процедуру, которая будет создавать новые записи в таблицах по определённым условиям.
|
||||
|
||||
\textbf{Формулировка задачи:} Создать функцию \texttt{convert\_to\_initials}, которая будет получать на вход строки с ФИО, а возвращать строку с инициалами. Создать процедуру \texttt{create\_participant\_request}, которая по заданной информации о соревновании, спортсмене и дивизионе будет создавать заявку на участие в соревновании.
|
||||
\textbf{Формулировка задачи:} Создать функцию \texttt{convert\_to\_initials}, которая будет получать на вход строки с ФИО, а возвращать строку с инициалами. Функция должна корректно обрабатывать случай, когда отчество отсутствует. Создать процедуру \texttt{create\_participant\_request}, которая по заданной информации о соревновании, спортсмене и дивизионе будет создавать заявку на участие в соревновании.
|
||||
|
||||
Код определения функции \texttt{convert\_to\_initials} представлен на Рис.~\ref{lst:convert_to_initials}. Функция принимает на вход три параметра типа \texttt{varchar}: \texttt{p\_name} -- имя, \texttt{p\_surname} -- фамилия, \texttt{p\_patronymic} -- отчество. Возвращает также \texttt{varchar} -- строку с инициалами. Если имя или фамилия не заданы, функция возвращает пустую строку. Функция также отдельно обрабатывает случай, когда не задано отчество, в таком случае инициалы будут состоять только из первой буквы имени и фамилии. Код запроса с использованием этой функции представлен на Рис.~\ref{lst:convert_query}, а результат его выполнения на Рис.~\ref{fig:conver_result}.
|
||||
Код определения функции \texttt{convert\_to\_initials} представлен на Рис.~\ref{lst:convert_to_initials}. Функция принимает на вход три параметра типа \texttt{varchar}: \texttt{p\_name} -- имя, \texttt{p\_surname} -- фамилия, \texttt{p\_patronymic} -- отчество. Возвращает также \texttt{varchar} -- строку с инициалами. Функция отдельно обрабатывает случай, когда не задано отчество, в таком случае инициалы будут состоять только из первой буквы имени и фамилии. Код запроса с использованием этой функции представлен на Рис.~\ref{lst:convert_query}, а результат его выполнения на Рис.~\ref{fig:conver_result}.
|
||||
|
||||
|
||||
\begin{lstlisting}[mathescape=true, caption={Код определения функции \texttt{convert\_to\_initials}.}, label={lst:convert_to_initials}]
|
||||
\begin{lstlisting}[caption={Код определения функции \texttt{convert\_to\_initials}.}, label={lst:convert_to_initials}]
|
||||
create or replace function convert_to_initials(
|
||||
p_name varchar,
|
||||
p_surname varchar,
|
||||
p_patronymic varchar
|
||||
) returns varchar as $$
|
||||
begin
|
||||
if p_name is null or p_name = '' or p_surname is null or p_surname = '' then
|
||||
return '';
|
||||
end if;
|
||||
|
||||
if p_patronymic is null or p_patronymic = '' then
|
||||
return concat(substring(p_name from 1 for 1), '. ', p_surname);
|
||||
end if;
|
||||
@@ -592,7 +588,7 @@ end;
|
||||
$$ language plpgsql;
|
||||
\end{lstlisting}
|
||||
|
||||
\begin{lstlisting}[mathescape=true, caption={Код запроса с использованием функции \texttt{convert\_to\_initials}.}, label={lst:convert_query}]
|
||||
\begin{lstlisting}[caption={Код запроса с использованием функции \texttt{convert\_to\_initials}.}, label={lst:convert_query}]
|
||||
select
|
||||
id_judge,
|
||||
convert_to_initials (name, surname, patronymic),
|
||||
@@ -612,7 +608,7 @@ from
|
||||
|
||||
Код определения процедуры \texttt{create\_participant\_request} представлен на Рис.~\ref{lst:procedure}. Процедура принимает на вход пять параметров типа \texttt{varchar}: \texttt{p\_name} -- имя спортсмена, \texttt{p\_surname} -- фамилия спортсмена, \texttt{p\_gender} -- пол спортсмена, \texttt{p\_competition\_title} -- название соревнования, \texttt{p\_division\_title} -- название дивизиона. Внутри процедуры сначала проверяется существование дивизиона в базе данных по переданному названию. Если дивизион не найден, выбрасывается ошибка. Затем проверяется существование соревнования. Если соревнование не существует, оно создаётся. Далее проверяется, существует ли спортсмен с указанными именем, фамилией и полом. Если спортсмен не найден, то создаётся новая запись о спортсмене. В конце создаётся заявка участника с указанием данных спортсмена, соревнования и дивизиона.
|
||||
|
||||
\begin{lstlisting}[mathescape=true, caption={Код определения процедуры \texttt{create\_participant\_request}.}, label={lst:procedure}]
|
||||
\begin{lstlisting}[caption={Код определения процедуры \texttt{create\_participant\_request}.}, label={lst:procedure}]
|
||||
create or replace procedure create_participant_request(
|
||||
p_name varchar(100),
|
||||
p_surname varchar(100),
|
||||
@@ -694,11 +690,6 @@ $$;
|
||||
t & Транзакция 1 & Транзакция 2 \\
|
||||
\hline
|
||||
|
||||
\multirow{3}{*}{} & \multicolumn{2}{p{0.9\textwidth}|}{
|
||||
В первой транзакции обновляется запись в таблице \texttt{judge}. В момент после обновления вторая транзакция читает эту же запись из \texttt{judge}, однако в связи с отсутствием артефакта <<Грязное чтение>> она видит исходную таблицу до обновлений первой транзакции.
|
||||
}\\
|
||||
\cline{2-3}
|
||||
|
||||
\multirow{2}{*}{}
|
||||
& \multicolumn{2}{c|}{
|
||||
\texttt{SET TRANSACTION ISOLATION LEVEL READ COMMITTED;}
|
||||
@@ -710,15 +701,15 @@ $$;
|
||||
|
||||
$t_1$ &
|
||||
\specialcell{
|
||||
Изменение имени судьи с \texttt{id\_judge = 201}\\ \\
|
||||
% \texttt{select id\_judge, name from judge}\\
|
||||
% \texttt{where id\_judge = 201;}\\
|
||||
Изменение имени судьи с \texttt{id\_judge = 201}\\
|
||||
\texttt{select id\_judge, name from judge}\\
|
||||
\texttt{where id\_judge = 201;}\\
|
||||
\texttt{update judge set name = 'Софа'}\\
|
||||
\texttt{where id\_judge = 201;}\\
|
||||
% \texttt{select id\_judge, name from judge}\\
|
||||
% \texttt{where id\_judge = 201;}\\
|
||||
\texttt{select id\_judge, name from judge}\\
|
||||
\texttt{where id\_judge = 201;}\\
|
||||
}
|
||||
\includegraphics[width=1\linewidth]{img/transaction1_2.png}
|
||||
\includegraphics[width=1\linewidth]{img/transaction1_1.png}
|
||||
&
|
||||
\\
|
||||
\hline
|
||||
@@ -727,7 +718,8 @@ $$;
|
||||
&
|
||||
\specialcell{
|
||||
Получение имени судьи с \texttt{id\_judge = 201} \\
|
||||
и завершение транзакции\\ \\
|
||||
и завершение транзакции\\
|
||||
\texttt{begin;} \\
|
||||
\texttt{select id\_judge, name from judge}\\
|
||||
\texttt{where id\_judge = 201;}\\
|
||||
\texttt{commit;}\\
|
||||
@@ -747,13 +739,18 @@ $$;
|
||||
&
|
||||
\\
|
||||
\hline
|
||||
|
||||
& \multicolumn{2}{p{0.9\textwidth}|}{
|
||||
В первой транзакции у судьи c \texttt{id\_judge = 201} изменяется имя с <<София>> на <<Софа>>. В момент после обновления вторая транзакция читает эту же запись из \texttt{judge}, однако в связи с отсутствием артефакта <<Грязное чтение>> она видит имя <<Софа>>, то есть значение до обновлений первой транзакции.
|
||||
}\\
|
||||
\hline
|
||||
\end{tabularx}
|
||||
\end{table}
|
||||
|
||||
|
||||
В таблице~\ref{tbl:unrepeatable_read} представлены транзакции, на примере которых демонстрируется наличие артефакта <<Неповторяемое чтение>>.
|
||||
|
||||
\newpage
|
||||
% \newpage
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
% \addtocounter{table}{-1}
|
||||
@@ -765,11 +762,6 @@ $$;
|
||||
t & Транзакция 1 & Транзакция 2 \\
|
||||
\hline
|
||||
|
||||
\multirow{3}{*}{} & \multicolumn{2}{p{0.9\textwidth}|}{
|
||||
В первой транзакции происходит чтение записи из таблицы \texttt{judge}. После чего эта же запись обновляется во второй транзакции, изменения фиксируются и вторая транзакция успешно завершается. Затем первая транзакция повторно считывает эту запись и получает обновлённые данные, а не исходные, из-за наличия артефакта <<Неповторяемое чтение>>.
|
||||
}\\
|
||||
\cline{2-3}
|
||||
|
||||
\multirow{2}{*}{}
|
||||
& \multicolumn{2}{c|}{
|
||||
\texttt{SET TRANSACTION ISOLATION LEVEL READ COMMITTED;}
|
||||
@@ -794,14 +786,33 @@ $$;
|
||||
&
|
||||
\specialcell{
|
||||
Изменение имени судьи с \texttt{id\_judge = 201} \\
|
||||
и фиксация транзакции\\ \\
|
||||
и фиксация транзакции\\
|
||||
\texttt{select id\_judge, name from judge}\\
|
||||
\texttt{where id\_judge = 201;}\\
|
||||
\texttt{update judge set name = 'Софа'}\\
|
||||
\texttt{where id\_judge = 201;}\\
|
||||
\texttt{select id\_judge, name from judge}\\
|
||||
\texttt{where id\_judge = 201;}\\
|
||||
\texttt{commit;}\\
|
||||
}
|
||||
\includegraphics[width=1\linewidth]{img/transaction2_2.png}
|
||||
\includegraphics[width=0.9\linewidth]{img/transaction2_2.png}
|
||||
\\
|
||||
\hline
|
||||
\end{tabularx}
|
||||
\end{table}
|
||||
|
||||
|
||||
\newpage
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
\addtocounter{table}{-1}
|
||||
\caption{Транзакции для демонстрации наличия артефакта <<Неповторяемое чтение>> (продолжение).}
|
||||
\label{tbl:unrepeatable_read}
|
||||
\footnotesize
|
||||
\begin{tabularx}{\textwidth}{|c|X|X|}
|
||||
\hline
|
||||
t & Транзакция 1 & Транзакция 2 \\
|
||||
\hline
|
||||
|
||||
$t_3$ &
|
||||
\specialcell{
|
||||
@@ -815,13 +826,18 @@ $$;
|
||||
&
|
||||
\\
|
||||
\hline
|
||||
|
||||
& \multicolumn{2}{p{0.9\textwidth}|}{
|
||||
В первой транзакции происходит получение имени судьи с \texttt{id\_judge = 201} -- выводится имя <<София>>. После чего эта же запись обновляется во второй транзакции, имя изменяется на <<Софа>>, изменения фиксируются и вторая транзакция успешно завершается. Затем первая транзакция повторно считывает эту запись и получает обновлённые данные -- имя <<Софа>>, из-за наличия артефакта <<Неповторяемое чтение>>.
|
||||
}\\
|
||||
\hline
|
||||
\end{tabularx}
|
||||
\end{table}
|
||||
|
||||
|
||||
В таблице~\ref{tbl:fantom} представлены транзакции, на примере которых демонстрируется наличие артефакта <<Фантомы>>.
|
||||
|
||||
\newpage
|
||||
% \newpage
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
% \addtocounter{table}{-1}
|
||||
@@ -833,11 +849,6 @@ $$;
|
||||
t & Транзакция 1 & Транзакция 2 \\
|
||||
\hline
|
||||
|
||||
\multirow{3}{*}{} & \multicolumn{2}{p{0.9\textwidth}|}{
|
||||
В первой транзакции происходит чтение записей из таблицы \texttt{judge} с \texttt{id\_judge >= 250}. После чего в эту таблицу добовляется запись во второй транзакции, изменения фиксируются и вторая транзакция успешно завершается. Затем первая транзакция повторно получает записи с \texttt{id\_judge >= 250}. В этот раз она также получает данные о записи, добавленной второй транзакцией, из-за наличия артефакта <<Фантомы>>.
|
||||
}\\
|
||||
\cline{2-3}
|
||||
|
||||
\multirow{2}{*}{}
|
||||
& \multicolumn{2}{c|}{
|
||||
\texttt{SET TRANSACTION ISOLATION LEVEL READ COMMITTED;}
|
||||
@@ -858,14 +869,34 @@ $$;
|
||||
\\
|
||||
\hline
|
||||
|
||||
\end{tabularx}
|
||||
\end{table}
|
||||
|
||||
\newpage
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
\addtocounter{table}{-1}
|
||||
\caption{Транзакции для демонстрации наличия артефакта <<Фантомы>> (продолжение).}
|
||||
\label{tbl:fantom}
|
||||
\footnotesize
|
||||
\begin{tabularx}{\textwidth}{|c|X|X|}
|
||||
\hline
|
||||
t & Транзакция 1 & Транзакция 2 \\
|
||||
\hline
|
||||
|
||||
|
||||
$t_2$ &
|
||||
&
|
||||
\specialcell{
|
||||
Добавление нового судьи и фиксация \\ транзакции\\ \\
|
||||
\texttt{select id\_judge, name from judge}\\
|
||||
\texttt{where id\_judge >= 250;}\\
|
||||
\texttt{insert into judge (name, surname,}\\
|
||||
\texttt{patronymic, category)}\\
|
||||
\texttt{values ('анна', 'иванова', 'петровна',}\\
|
||||
\texttt{'высшая');}\\
|
||||
\texttt{values ('вика', 'иванова', 'петровна',}\\
|
||||
\texttt{'высшая');}\\
|
||||
\texttt{select id\_judge, name from judge}\\
|
||||
\texttt{where id\_judge >= 250;}\\
|
||||
\texttt{commit;}\\
|
||||
}
|
||||
\includegraphics[width=1\linewidth]{img/transaction3_2.png}
|
||||
@@ -883,21 +914,27 @@ $$;
|
||||
&
|
||||
\\
|
||||
\hline
|
||||
|
||||
& \multicolumn{2}{p{0.9\textwidth}|}{
|
||||
В первой транзакции происходит получение имён судей из таблицы \texttt{judge} с \texttt{id\_judge >= 250}, в ответ выводится один судья с именем <<анна>>. После чего в эту таблицу добовляется новый судья во второй транзакции с именем <<вика>>, изменения фиксируются и вторая транзакция успешно завершается. Затем первая транзакция повторно получает записи с \texttt{id\_judge >= 250}. В этот раз, по мимо судьи с именем <<анна>>, она также получает данные о записи, добавленной второй транзакцией -- судье с именем <<вика>>, эта запись и является артефактом <<Фантом>>.
|
||||
}\\
|
||||
\hline
|
||||
\end{tabularx}
|
||||
\end{table}
|
||||
|
||||
\newpage
|
||||
\section*{Заключение}
|
||||
\addcontentsline{toc}{section}{Заключение}
|
||||
В ходе освоения данного курса было выполнено пять лабораторных работ:
|
||||
\begin{enumerate}
|
||||
\item Создано представление, инкапсулирующее запрос. Продемонстрирована невозможность модификации представления; написан запрос, использующий в себе созданное представление.
|
||||
\item Создана таблица подсчёта количества соревнований для каждого судьи. Также созданы триггеры, автоматизирующие сбор статистики в таблице.
|
||||
\item Созданы два пользователя с различными правами доступа. Первый пользователь наделён правами только на просмотр представления, а второй наделён правами просмотра, вставки, удаления и обновления данных во всех таблицах, участвующих в представлении. Продемонстрировано поведение СУБД при различных операциях для каждого пользователя, в том числе при недопустимых.
|
||||
\item Создана таблица подсчёта количества соревнований для каждого судьи. Также созданы 5 триггеров, автоматизирующие сбор статистики в таблице.
|
||||
\item Созданы 2 пользователя с различными правами доступа. Первый пользователь наделён правами только на просмотр представления, а второй наделён правами просмотра, вставки, удаления и обновления данных во всех таблицах, участвующих в представлении. На 8 примерах продемонстрировано поведение СУБД при различных операциях для каждого пользователя, в том числе при недопустимых.
|
||||
\item Созданы процедура и функция. Функция принимает на вход фамилию, имя и отчество человека и возвращает фамилию и его инициалы.
|
||||
\item Управление транзакциями. Задан уровень изоляции транзакций как Read Committed и продемонстрировано отсутствие артефакта <<Грязное чтение>> и наличие артефактов <<Неповторяемое чтение>> и <<Фантомы>>.
|
||||
\end{enumerate}
|
||||
|
||||
На работу было потрачено около 2-х месяцев, за которые было написано более пятисот строк кода.
|
||||
На работу было потрачено около 2-х месяцев, за которые было написано более 500 строк кода.
|
||||
|
||||
Работа была выполнена в системе управления базами данных PostgreSQL 16.2.
|
||||
|
||||
|
||||