
Лёшка / Маркин Тест 3 / SQL / Козадаев М.М._5-6_7
.doc
Козадаев М.М. |
635 гр. |
7 вариант |
Лабораторная работа № 5.
Построение запросов на модификацию данных
Цель работы. Приобретение практических навыков построения запросов на модификацию данных.
Лабораторное задание. Изучить теоретическую часть, изложенную в гл. 5 учебного пособия. Восстановить учебную БД из резервной копии. Построить и выполнить запросы к таблицам учебной БД. Защитить лабораторную работу.
-
Создаем таблицу PATTERN, используя следующий запрос:
CREATE TABLE PATTERN
(FINT INTEGER,
FCHAR30 VARCHAR(30),
FCHAR40 VARCHAR (40),
FCHAR8 VARCHAR (8),
FNUMERIC NUMERIC(18,4),
FDATE DATE);.
Таблица PATTERN предназначена для временного хранения данных разного типа, извлекаемых из таблиц учебной БД. Если некоторые поля таблицы PATTERN не используются, то их значения будут содержать NULL-значения.
-
Поместим в таблицу PATTERN информацию о средних значениях начислений, приходящихся на каждый месяц. При этом столбец FCHAR30 должен содержать номер месяца и год начисления, столбец FNUMERIC - среднее значение начислений.
Запрос:
INSERT INTO PATTERN (FCHAR30,FNUMERIC)
SELECT n.nachislmonth||'.'||n.nachislyear, AVG (n.nachislsum)
FROM nachislsumma n
GROUP BY 1;
Результат выполнения:
-
Поместим в таблицу PATTERN информацию об абонентах, проживающих на улице ВОЙКОВ ПЕРЕУЛОК. При этом столбец FCHAR30 должен содержать ФИО абонента, а столбец FCHAR40 –номер дома и номер квартиры, в которой проживает абонент.
Запрос:
INSERT INTO PATTERN (FCHAR30,FCHAR40)
SELECT a.fio, a.houseno||'-'||a.flatno
FROM abonent a INNER JOIN street s ON a.streetcd=s.streetcd
WHERE s.streetnm='ВОЙКОВ ПЕРЕУЛОК';
Результат выполнения:
-
Поместить в таблицу PATTERN информацию о заявках и абонентах, которые их сделали. При этом столбец FNUMERIC должен содержать номер заявки, столбец FDATE – дату подачи заявки, столбец FCHAR30 – имя абонента, сделавшего заявку, столбец FCHAR8 – номер лицевого счета абонента, а столбец FCHAR40 – название улицы, на которой проживает данный абонент.
Запрос:
INSERT INTO PATTERN (FNUMERIC,FDATE,FCHAR30,FCHAR8,FCHAR40)
SELECT r.requestcd, r.incomingdate, a.fio, a.accountcd, s.streetnm
FROM abonent a INNER JOIN street s ON a.streetcd=s.streetcd
INNER JOIN request r ON a.accountcd=r.accountcd
Результат выполнения:
-
С помощью однострочного оператора INSERT поместим в таблицу ремонтных заявок новую заявку от абонента с ФИО Шубина Т. П. Исполнителем этой заявки назначим мастера с ФИО Шубин В. Г. В качестве даты подачи заявки зададим дату, равную текущей, уменьшенной на один месяц. В качестве неисправности укажем Плохое поступление газа на горелку плиты. Дата выполнения заявки не должна быть определена.
Запрос:
INSERT INTO REQUEST(accountcd,executorcd,failurecd, requestcd,incomingdate)
VALUES ((SELECT accountcd FROM abonent WHERE FIO='Шубина Т.П.'),
(SELECT executorcd FROM executor WHERE FIO='Шубин В.Г.'),
(SELECT d.failurecd FROM disrepair d WHERE d.failurenm='Плохое поступление газа на горелку плиты'),
(SELECT MAX(requestcd)+1 FROM request),
(dateadd(month,(-1), current_date)))
Результат выполнения:
-
Установим для новой заявки дату выполнения равной текущей дате.
Запрос:
UPDATE request
SET executiondate=current_date
WHERE requestcd=(SELECT MAX(requestcd) FROM request)
Результат выполнения:
-
Добавим в таблицу регистрации фактов оплаты за услуги новый факт оплаты, принятой от абонента с ФИО Шмаков С.В. Все параметры оплаты зададим произвольно.
Запрос:
INSERT INTO paysumma(PayFactCd,accountcd,servicecd,Paysum, paydate, payMonth, payYear)
VALUES ((SELECT MAX(PayFactCd)+1 FROM paysumma),
(SELECT accountcd FROM abonent WHERE FIO='Шмаков С.В.'),
4, 100, current_date, 8, 2010)
Результат выполнения:
Вариант 7:
1. Увеличить на 10 руб. все значения начислений за 2008 г. всем абонентам.
Запрос:
UPDATE NACHISLSUMMA SET NACHISLSUM = NACHISLSUM + 10 WHERE NachislYear = '2008';
Исходная таблица:
Результат выполнения:
2. Удалить всех исполнителей, за которыми закреплено менее 4 ремонтных заявок.
Запрос:
DELETE from executor where executorcd IN (select executorcd from REQUEST group by executorcd having (executorcd is not NULL) and COUNT(*) < 4)
Исходная таблица:
Результат выполнения:
3. Перевести всех абонентов с улиц с названием МОСКОВСКАЯ УЛИЦА и МОСКОВСКОЕ ШОССЕ на улицу с названием ВОЙКОВ ПЕРЕУЛОК.
Запрос:
UPDATE ABONENT SET
StreetCD=(Select StreetCD from street where streetnm='ВОЙКОВ ПЕРЕУЛОК')
WHERE StreetCD=(Select StreetCD from street where streetnm='МОСКОВСКАЯ УЛИЦА') OR
StreetCD=(Select StreetCD from street where streetnm='МОСКОВСКОЕ ШОССЕ');
Исходная таблица:
Результат выполнения:
4. Удалить информацию о платежах всех абонентов с номером лицевого счета менее 115705.
Запрос:
DELETE from paysumma
where accountcd<115705
Исходная таблица:
Результат выполнения:
5. Удалить информацию о платежах всех абонентов, у которых нет невыполненных ремонтных заявок.
Запрос:
DELETE from paysumma where accountcd IN
(select accountcd from REQUEST where executiondate is not null)
Исходная таблица:
Результат выполнения:
Лабораторная работа № 5.
Программирование хранимых процедур
Цель работы. Приобретение практических навыков программирования хранимых процедур.
Лабораторное задание. Изучить теоретическую часть, изложенную в разд. 6.1 и 6.2 учебном пособии. Восстановить учебную БД из резервной копии. Разработать и выполнить хранимые процедуры согласно заданиям. Защитить лабораторную работу.
1) Изменить (используя оператор ALTER PROCEDURE) процедуру
FACTORIALSET таким образом, чтобы при ее вызове не требовалось указывать входные параметры, а вычисление факториала чисел от 1 до 170 и занесение вычисленных значений в таблицу FTABLE происходило автоматически. При этом генерация очередного значения для вычисления факториала должна осуществляться с помощью генератора. Перед каждым запуском на выполнение процедуры FACTORIALSET необходимо устанавливать начальное значение генератора равным нулю.
Скрипт:
create generator Fact_numb;
ALTER PROCEDURE FactorialSet
AS
DECLARE VARIABLE i INTEGER;
DECLARE VARIABLE f DOUBLE PRECISION;
BEGIN
DELETE FROM Ftable;
i = GEN_ID(Fact_numb, 0);
WHILE ( i <= 170) DO
BEGIN
EXECUTE PROCEDURE Factorial (i)
RETURNING_VALUES f;
INSERT INTO Ftable (Fnum, Fvalue) VALUES (:i, :f);
i=GEN_ID(Fact_numb, 1);
END
END
Запросы:
set generator Fact_numb to 0;
execute procedure FactorialSet;
Результат:
-
Создать таблицу, позволяющую сохранять следующую информацию: код исполнителя ремонтной заявки (первичный ключ таблицы), ФИО исполнителя и количество выполненных им заявок.
Скрипт:
CREATE TABLE MyTable (ExecutorCD INTEGER NOT NULL PRIMARY KEY, FIO VARCHAR(20), ExecutedCol INTEGER);
Результат:
-
Создать две хранимых процедуры. Первая процедура по заданному номеру лицевого счета абонента должна возвращать код исполнителя, который последним выполнял ремонтную заявку, поданную данным абонентом. Вторая процедура должна заполнять созданную таблицу, при этом используя результаты вызова первой процедуры и перезаписывая информацию о количестве заявок исполнителя, если по этому исполнителю уже есть данные в таблице.
1-я процедура:
CREATE PROCEDURE AbExecutor (AcCD VARCHAR(6))
RETURNS (ExecCD INTEGER)
AS
DECLARE TAcCD VARCHAR(6);
DECLARE TExCD INTEGER;
DECLARE TDate DATE;
DECLARE MaxDate DATE = NULL;
DECLARE TExCDLast INTEGER;
DECLARE Req CURSOR FOR
(SELECT ExecutorCD, ExecutionDate FROM Request WHERE AccountCD = :AcCD);
BEGIN
OPEN Req;
WHILE (1=1) DO
BEGIN
FETCH Req INTO :TExCD, :TDate;
IF (ROW_COUNT=0) THEN LEAVE;
IF (TDate IS NOT NULL) THEN
IF (MaxDate IS NULL) THEN
BEGIN
MaxDate = TDate;
TExCDLast = TExCD;
END
ELSE IF (MaxDate < TDATE) THEN
BEGIN
MaxDate = TDATE;
TExCDLast = TExCD;
END
END
CLOSE Req;
ExecCD = TExCDLast;
SUSPEND;
END
Пример работы:
Execute procedure AbExecutor('005488')
Результат:
2-я процедура:
CREATE PROCEDURE MyTableInsert
AS
DECLARE TAcCD VARCHAR(6);
DECLARE TExec INTEGER;
DECLARE ExCol INTEGER;
DECLARE i INTEGER=0;
DECLARE AbonC CURSOR FOR
(SELECT DISTINCT AccountCD FROM Request);
BEGIN
DELETE FROM MyTable;
OPEN AbonC;
WHILE (1=1) DO
BEGIN
ExCol = 0;
FETCH AbonC INTO :TAcCD;
IF (ROW_COUNT=0) THEN LEAVE;
EXECUTE PROCEDURE AbExecutor(:TAcCD) RETURNING_VALUES :TExec;
SELECT ExecutedCol FROM MyTable WHERE EXECUTORCD = :TExec INTO :ExCol;
IF (ExCol IS NULL) THEN ExCol = 1;
ELSE ExCol = ExCol + 1;
UPDATE OR INSERT INTO MyTable VALUES
(:TExec, (SELECT FIO FROM EXECUTOR WHERE EXECUTORCD = :TExec), :ExCol);
END
END
Пример работы:
EXECUTE PROCEDURE MyTableInsert;
Результат:
Общий скрипт:
CONNECT 'd:\Учёба\РГРТУ\SQL, Маркин\Lab\NN.fdb' USER 'SYSDBA' PASSWORD 'masterkey';
CREATE TABLE MyTable (ExecutorCD INTEGER NOT NULL PRIMARY KEY, FIO VARCHAR(20), ExecutedCol INTEGER);
SET TERM !! ;
CREATE PROCEDURE AbExecutor (AcCD VARCHAR(6))
RETURNS (ExecCD INTEGER)
AS
DECLARE TAcCD VARCHAR(6);
DECLARE TExCD INTEGER;
DECLARE TDate DATE;
DECLARE MaxDate DATE = NULL;
DECLARE TExCDLast INTEGER;
DECLARE Req CURSOR FOR
(SELECT ExecutorCD, ExecutionDate FROM Request WHERE AccountCD = :AcCD);
BEGIN
OPEN Req;
WHILE (1=1) DO
BEGIN
FETCH Req INTO :TExCD, :TDate;
IF (ROW_COUNT=0) THEN LEAVE;
IF (TDate IS NOT NULL) THEN
IF (MaxDate IS NULL) THEN
BEGIN
MaxDate = TDate;
TExCDLast = TExCD;
END
ELSE IF (MaxDate < TDATE) THEN
BEGIN
MaxDate = TDATE;
TExCDLast = TExCD;
END
END
CLOSE Req;
ExecCD = TExCDLast;
SUSPEND;
END !!
CREATE PROCEDURE MyTableInsert
AS
DECLARE TAcCD VARCHAR(6);
DECLARE TExec INTEGER;
DECLARE ExCol INTEGER;
DECLARE AbonC CURSOR FOR
(SELECT DISTINCT AccountCD FROM Request);
BEGIN
DELETE FROM MyTable;
OPEN AbonC;
WHILE (1=1) DO
BEGIN
ExCol = 0;
FETCH AbonC INTO :TAcCD;
IF (ROW_COUNT=0) THEN LEAVE;
EXECUTE PROCEDURE AbExecutor(:TAcCD) RETURNING_VALUES :TExec;
SELECT ExecutedCol FROM MyTable WHERE EXECUTORCD = :TExec INTO :ExCol;
IF (ExCol IS NULL) THEN ExCol = 1;
ELSE ExCol = ExCol + 1;
UPDATE OR INSERT INTO MyTable VALUES
(:TExec, (SELECT FIO FROM EXECUTOR WHERE EXECUTORCD = :TExec), :ExCol);
END
END !!
SET TERM ; !!