Кашина_ТРиЗБД_ЛБ6
.docxМинистерство науки и высшего образования Российской Федерации Федеральное государственное бюджетное образовательное учреждение высшего образования
«Владимирский государственный университет
имени Александра Григорьевича и Николая Григорьевича Столетовых» (ВлГУ)
Колледж инновационных технологий и предпринимательства
КАФЕДРА ФИЗИКИ И ПРИКЛАДНОЙ МАТЕМАТИКИ
Лабораторная работа № 6
по дисциплине «Технология разработки и защиты баз данных»
на тему: «Основы программирования с помощью встроенного языка TRANSACT-SQL в MS SQL Server.»
Выполнил
студент группы ИПсп-123
Кашина Д. А.
Принял
Кабанова М.Ю.
Владимир, 2025
Цель работы:
1. Изучить используемый в реляционных СУБД встроенный язык программирования TransactSQL для написания программ в MS SQL Server.
2. Изучить правила построения идентификаторов, правила объявления переменных и их типов.
3. Изучить принципы работы с циклами и ветвлениями.
4. Изучить работу с переменными типа Table.
5. Изучить синтаксис и семантику функций и хранимых процедур Transact– SQL: способов их идентификации, методов задания и спецификации параметров и возвращаемых значений, и вызовов функций и хранимых процедур.
Ход работы:
Самостоятельные запросы
/*Кашина 2.10.25
Подсчитать среднюю зарплату преподавателей(с помощью SELECT) и умножить ее на 123.34,
которое необходимо сохранить в отдельной переменной, и вывести значение переменной на экран*/
USE University_Кашина_Диана
DECLARE @avg_salary DECIMAL(10,2);
DECLARE @result DECIMAL(10,2);
SELECT @avg_salary = AVG(salary+rise) FROM Teacher
SET @result = @avg_salary * 123.34;
SELECT @result AS результат;
/*Кашина 2.10.25
Подсчитать суммарное значение всех стипендий у студентов, результат поместить
в переменную, вывести значение переменной на экран.*/
USE University_Кашина_Диана
DECLARE @total_stipend DECIMAL(10,2);
SELECT @total_stipend = SUM(Stipend) FROM Student1;
SELECT @total_stipend AS общая_сумма_стипендий;
Подсчитать количество кафедр, результат поместить в переменную, вывести значение переменной на экран.
/*Кашина 2.10.25
Подсчитать количество кафедр, результат поместить в переменную,
вывести значение переменной на экран*/
USE University_Кашина_Диана
DECLARE @count_kafedr INT;
SELECT @count_kafedr = COUNT(*) FROM Kafedra;
SELECT @count_kafedr AS 'Количество кафедр';
Создать локальную таблицу с названием TEMP и полями типа дата/время, длинное целое, строка. Добавить в нее две записи с данными и вывести результат на экран.
/*Кашина 2.10.25
Создать локальную таблицу с названием TEMP и полями типа дата/время,
длинное целое, строка. Добавить в нее две записи с данными и вывести результат на экран.*/
USE University_Кашина_Диана
--Создание временной таблицы
CREATE TABLE #TEMP1 (
date_time_column DATETIME,
big_int_column BIGINT,
string_column NVARCHAR(100)
);
-- Добавление данных с правильным форматом даты
INSERT INTO #TEMP (date_time_column, big_int_column, string_column) VALUES
('20240115 10:30:00', 123456789, 'Первая запись'),
('20240116 14:45:30', 987654321, 'Вторая запись');
-- Вывод результата
SELECT * FROM #TEMP;
Подсчитать количество факультетов. Если их в таблице от 2 до 4, то ничего не сообщать, в противном случае вывести сообщение вида "В таблице ... факультетов" (вместо многоточия поставить точное количество факультетов).
/* Кашина 2.10.25
Подсчитать количество факультетов. Если их в таблице от 2 до 4, то ничего не
сообщать, в противном случае вывести сообщение вида "В таблице ... факультетов" (вместо
многоточия поставить точное количество факультетов).*/
USE University_Кашина_Диана
DECLARE @faculty_count INT;
SELECT @faculty_count = COUNT(*) FROM Facultet;
IF @faculty_count < 2 OR @faculty_count > 4
BEGIN
PRINT 'В таблице ' + CONVERT(VARCHAR, @faculty_count) + ' факультетов';
END;
Подсчитать средний год рождения студентов. Если полученный год в диапазоне от 1980 до 1999, то ничего не сообщать, в противном случае вывести сообщение вида "Средний год рождения = ." (вместо многоточия поставить точный средний год).
/*Кашина 2.10.25
Подсчитать средний год рождения студентов. Если полученный год в диапазоне
от 1980 до 1999, то ничего не сообщать, в противном случае вывести сообщение вида "Средний
год рождения = ." (вместо многоточия поставить точный средний год).*/
USE University_Кашина_Диана
DECLARE @avg_birth_year INT;
SELECT @avg_birth_year = AVG(YEAR(Birthday))
FROM Student1;
IF @avg_birth_year < 1980 OR @avg_birth_year > 1999
BEGIN
PRINT 'Средний год рождения = ' + CONVERT(VARCHAR, @avg_birth_year);
END;
Определить количество записей в таблице кафедра. Пока записей меньше 10, делать в цикле добавление записи в временную таблицу с автоматическим наращиванием значения ключевого поля, а вместо названия кафедры ставить значение 'Имя не известно'.
/*Кашина 2.10.25
Определить количество записей в таблице кафедра. Пока записей меньше 10,
делать в цикле добавление записи в временную таблицу с автоматическим наращиванием
значения ключевого поля, а вместо названия кафедры ставить значение 'Имя не известно'.*/
USE University_Кашина_Диана
-- Создаем временную таблицу
CREATE TABLE #temp_kafedra (
id INT IDENTITY(1,1) PRIMARY KEY,
name NVARCHAR(100) NOT NULL
);
-- Определяем начальное количество записей
DECLARE @record_count INT;
SELECT @record_count = COUNT(*) FROM Kafedra;
-- Цикл добавления записей
WHILE @record_count < 10
BEGIN
INSERT INTO #temp_kafedra (name) VALUES ('Имя не известно');
SET @record_count = @record_count + 1;
END;
-- Выводим результат
SELECT * FROM #temp_kafedra;
SELECT 'Итоговое количество записей: ' + CONVERT(VARCHAR, @record_count) AS результат;
Создать пользовательскую функцию, которая будет возвращать результат в виде таблицы, а именно выводить всех учащихся студентов по кафедрам с указанием курса. При этом функция имеет один параметр @city, с помощью которого введем ограничение на вычисление, а именно город проживания должен быть Ростов-на-Дону.
/*Кашина 9.10.25
Создать пользовательскую функцию, которая будет возвращать результат в виде
таблицы, а именно выводить всех учащихся студентов по кафедрам с указанием курса. При этом
функция имеет один параметр @city, с помощью которого введем ограничение на вычисление,
а именно город проживания должен быть Ростов-на-Дону. */
CREATE FUNCTION dbo.GetStudentsByDepartment(@city VARCHAR(50))
RETURNS TABLE
AS
RETURN (
SELECT
s.Student_ID,
s.Sutname + ' ' + s.Sutfname AS 'Полное имя',
s.kod_kafedru AS 'Код кафедры',
s.Kurs AS 'Курс',
s.City,
s.Groupname
FROM Student1 s
WHERE s.City = @city
);
GO
-- Вызов функции для получения студентов из Ростова-на-Дону
SELECT * FROM dbo.GetStudentsByDepartment('Ростов-на-Дону');
Создать процедуру Count_Assistent_Salary_Title c входными параметрами @Sum_salary целого типа, @Title строка с длиной 15 символов, которая определяет кол-во преподавателей, должность которых совпадает с параметром @Title и зарплата у которых не менее заданного параметра @Sum_salary.
/*кашина 10.10
Создать процедуру Count_Assistent_Salary_Title c входными параметрами
@Sum_salary целого типа, @Title строка с длиной 15 символов, которая определяет кол-во
преподавателей, должность которых совпадает с параметром @Title и зарплата у которых не
менее заданного параметра @Sum_salary.*/
CREATE PROCEDURE Count_Assistent_Salary_Title
@Sum_salary INT,
@Title VARCHAR(15)
AS
BEGIN
SELECT COUNT(*) AS TeacherCount
FROM Teacher
WHERE dolgnost = @Title
AND salary >= @Sum_salary;
END;
Создать процедуру update_proc_rise с входным параметром и значением по умолчанию @p real = 0.5 для увеличения значения надбавки к зарплате в таблице Teacher в заданное количество раз. Процедура не возвращает никаких данных.
/*Создать процедуру update_proc_rise с входным параметром и значением по
умолчанию @p real = 0.5 для увеличения значения надбавки к зарплате в таблице Teacher в
заданное количество раз. Процедура не возвращает никаких данных.*/
-- Первый пакет: удаление процедуры если существует
USE University_Кашина_Диана
IF OBJECT_ID('update_proc_rise', 'P') IS NOT NULL
DROP PROCEDURE update_proc_rise;
GO -- Разделитель пакетов
-- Второй пакет: создание процедуры
CREATE PROCEDURE update_proc_rise
@p REAL = 0.5
AS
BEGIN
UPDATE Teacher
SET salary = salary * @p;
PRINT 'Надбавка к зарплате увеличена в ' + CAST(@p AS VARCHAR(10)) + ' раз(а)';
PRINT 'Обновлено записей: ' + CAST(@@ROWCOUNT AS VARCHAR(10));
END;
GO
/*Кашина 10.10.25
Вызов процедуры*/
USE University_Кашина_Диана
EXEC update_proc_rise 1.5
Задания по собственному варианту
один запрос для создания временной таблицы через переменную типа TABLE;
/*Кашина 10.10.25
1 запрос по собственному варианту*/
-- Временная таблица для статистики заказов по клиентам
DECLARE @ClientOrderStats TABLE (
ClientName VARCHAR(MAX),
OrderCount INT,
TotalSpent MONEY
);
-- Заполняем данными о заказах клиентов
INSERT INTO @ClientOrderStats
SELECT
c.Name,
COUNT(o.ID_Order),
SUM(o.Total_Cost)
FROM Client c
INNER JOIN [Order] o ON c.ID_Client = o.ID_Client
GROUP BY c.Name;
-- Выводим результаты
SELECT * FROM @ClientOrderStats
ORDER BY TotalSpent DESC;
один запрос с использованием условной конструкции IF;
/*Кашина 10.10.25
– один запрос с использованием условной конструкции IF; */
DECLARE @active_couriers int
DECLARE @status_message varchar(50)
-- Считаем курьеров с активными статусами (в пути)
SET @active_couriers = (SELECT COUNT(*) FROM Courier WHERE Employment_status = 'в пути')
IF @active_couriers > 0 BEGIN
SET @status_message = 'Активных курьеров: ' + CAST(@active_couriers AS varchar)
SELECT @status_message AS 'Статус'
-- Показываем активных курьеров
SELECT
Name AS 'Имя курьера',
Number AS 'Телефон',
Delivery_Area AS 'Район доставки'
FROM Courier
WHERE Employment_status = 'в пути'
END ELSE BEGIN
SET @status_message = 'Нет активных курьеров в пути'
SELECT @status_message AS 'Статус'
-- Показываем всех курьеров с их статусами
SELECT
Name AS 'Имя курьера',
Number AS 'Телефон',
Delivery_Area AS 'Район',
Employment_status AS 'Статус'
FROM Courier
WHERE Employment_status IS NOT NULL
END
один запрос с использованием цикла WHILE;
/*Кашина 10.10.25
– один запрос с использованием цикла WHILE */
DECLARE @discount_count INT = 1
DECLARE @total_discounts INT
-- Считаем заказы со скидкой
SET @total_discounts = (SELECT COUNT(*) FROM [Order] WHERE Discount > 0)
PRINT 'Заказы со скидкой:'
WHILE @discount_count <= @total_discounts
BEGIN
PRINT 'Заказ №' + CAST(@discount_count AS VARCHAR) + ' имеет скидку'
-- Выходим если дошли до 5 заказов
IF @discount_count = 5
BREAK
SET @discount_count = @discount_count + 1
END
PRINT 'Проверено заказов: ' + CAST(@discount_count AS VARCHAR)
один запрос для создания скалярной функции
/*Кашина 10.10.25
4. один запрос для создания скалярной функции*/
-- Функция для форматирования адреса клиента
CREATE FUNCTION FormatClientAddress(
@city VARCHAR(MAX),
@street VARCHAR(MAX),
@house INT
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @full_address VARCHAR(MAX)
SET @full_address = 'г. ' + @city + ', ул. ' + @street + ', д. ' + CAST(@house AS VARCHAR)
RETURN @full_address
END
/*Кашина 10.10.25
вызов скалярной функции*/
SELECT
Name,
dbo.FormatClientAddress(City, Street, House) AS 'Полный адрес'
FROM Client;
один запрос для создания функции, которая возвращает табличное значение;
/*Кашина 10.10.25
– один запрос для создания функции, которая возвращает табличное значение*/
-- Функция возвращает всех клиентов из указанного города
CREATE FUNCTION GetClientsByCity(@city_name VARCHAR(MAX))
RETURNS TABLE
AS
RETURN
(
SELECT
ID_Client,
Name AS 'Имя_Клиента',
Street,
House,
Apartment,
Number AS 'Номер телефона'
FROM Client
WHERE City = @city_name);
/*Кашина 10.10.25*/
-- Получить всех клиентов из Москвы
SELECT * FROM dbo.GetClientsByCity('Москва');
-- Получить клиентов из Владимира с сортировкой по имени
SELECT
ClientName,
Street,
House,
PhoneNumber
FROM dbo.GetClientsByCity('Владимир')
ORDER BY ClientName;
один запрос для создания процедуры без параметров
/*Кашина 10.10.25
один запрос для создания процедуры без параметров*/
-- Процедура показывает топ-5 самых популярных пицц
CREATE PROCEDURE GetTopPizzas
AS
BEGIN
SELECT TOP 5
p.Name AS 'Название',
SUM(po.Quantity) AS 'Общее_Количество',
SUM(po.Quantity * ps.Price) AS 'Выручка'
FROM Pizza p
INNER JOIN Pizza_Order po ON p.ID_Pizza = po.ID_Pizza
INNER JOIN Pizza_Size ps ON p.ID_Pizza_Size = ps.ID_Pizza_Size
GROUP BY p.Name
ORDER BY Общее_Количество DESC;
END;
/*Кашина 10.10.25
вызов процедуры*/
EXEC GetTopPizzas;
один запрос для создания процедуры c входным параметром
/*Кашина 10.10.25
один запрос для создания процедуры c входным параметром*/
-- Процедура показывает заказы клиента по его ID
CREATE PROCEDURE GetClientOrders
@client_id INT -- входной параметр
AS
BEGIN
SELECT
o.ID_Order AS 'Номер заказа',
o.Order_Time AS 'Время заказа',
o.Order_Status AS 'Статус',
o.Total_Cost AS 'Стоимость',
o.Discount AS 'Скидка %',
(o.Total_Cost * (100 - ISNULL(o.Discount, 0)) / 100) AS 'Итоговая сумма'
FROM [Order] o
WHERE o.ID_Client = @client_id
ORDER BY o.Order_Time DESC;
END;
/*Кашина 10.10.25
вызов функции*/
-- Получить заказы клиента с ID = 17
EXEC GetClientOrders @client_id = 17;
-- Получить заказы клиента с ID = 19
EXEC GetClientOrders 19;
один запрос для создания процедуры c входными параметрами и RETURN
/*кашина 10.10.25
один запрос для создания процедуры c входными параметрами и RETURN*/
-- Процедура возвращает общее количество заказов клиента
CREATE PROCEDURE GetClientOrderCount
@client_id INT -- входной параметр
AS
BEGIN
DECLARE @order_count INT;
-- Считаем количество заказов клиента
SELECT @order_count = COUNT(*)
FROM [Order]
WHERE ID_Client = @client_id;
-- Возвращаем результат через RETURN
RETURN @order_count;
END;
/*кашина 10.10.25
один запрос для создания процедуры c входными параметрами и RETURN
вызов функции*/
-- Объявляем переменную для получения результата
DECLARE @result INT;
-- Вызываем процедуру и получаем результат через RETURN
EXEC @result = GetClientOrderCount @client_id = 17;
-- Выводим результат
PRINT 'Количество заказов клиента: ' + CAST(@result AS VARCHAR);
один запрос для создания процедуры обновления данных в таблице базы данных UPDATE;
/*Кашина 10.10.25
один запрос для создания процедуры обновления данных в таблице базы данных UPDATE*/
-- Процедура для обновления статуса заказа
CREATE PROCEDURE UpdateOrderStatus
@order_id INT,
@new_status VARCHAR(MAX)
AS
BEGIN
-- Обновляем статус заказа
UPDATE [Order]
SET Order_Status = @new_status
WHERE ID_Order = @order_id;
-- Проверяем сколько строк было обновлено
IF @@ROWCOUNT > 0
PRINT 'Статус заказа №' + CAST(@order_id AS VARCHAR) + ' успешно обновлен на: ' + @new_status;
ELSE
PRINT 'Заказ с ID ' + CAST(@order_id AS VARCHAR) + ' не найден!';
END;
/*Кашина 10.10.25
выполнение процедуры*/
-- Обновить статус заказа на "доставлен"
EXEC UpdateOrderStatus
@order_id = 11,
@new_status = 'доставлен';
один запрос для создания процедуры извлечения данных из таблиц базы данных SELECT.
/*Кашина 10.10.25
один запрос для создания процедуры извлечения данных из таблиц базы данных SELECT*/
-- Процедура для извлечения статистики продаж пицц
CREATE PROCEDURE GetPizzaSalesStats
AS
BEGIN
SELECT
p.Name AS 'Пицца',
pz.Name AS 'Пиццерия',
SUM(po.Quantity) AS 'Количество продаж',
SUM(po.Quantity * ps.Price) AS 'Общая выручка',
AVG(ps.Price) AS 'Средняя цена'
FROM Pizza p
INNER JOIN Pizza_Order po ON p.ID_Pizza = po.ID_Pizza
INNER JOIN Pizza_Size ps ON p.ID_Pizza_Size = ps.ID_Pizza_Size
INNER JOIN Pizzeria pz ON p.ID_Pizzeria = pz.ID_Pizzeria
INNER JOIN [Order] o ON po.ID_Order = o.ID_Order
WHERE o.Order_Status = 'доставлен'
GROUP BY p.Name, pz.Name
ORDER BY SUM(po.Quantity) DESC;
END;
/*Кашина 10.10.25
один запрос для создания процедуры извлечения данных из таблиц базы данных SELECT
выполнение процедуры*/
EXEC GetPizzaSalesStats;
Вывод: в ходе лабораторной работы были изучены используемые в реляционной СУБД встроенный язык программирования TransactSQL для написание программ в MS SQL Server. Изучены правила построения идентификаторов, правила объявления переменных и их типов. Изучены принципы работы с циклами и ветвлениями. Изучена работа с переменными типа Table. Изучен синтаксист и семантика функций и хранимых процедур.
