
Лабы / Лаб5-6
.docxФЕДЕРАЛЬНОЕ АГЕНТСТВО СВЯЗИ
Федеральное государственное образовательное бюджетное учреждение
высшего профессионального образования
Московский технический университет связи и информатики
Кафедра интеллектуальных систем управления и автоматизации
Лабораторная работа №5-6
по дисциплине
Базы данных
Москва 2017
Хранимая процедура Customer_Insert
Галерее View Ridge требуется возможность добавлять в базу данных новых клиентов и записывать информацию о художниках, работами которых клиенты интересуются. В частности, нужно записывать имя и телефоны клиента, а также ассоциировать его со всеми художниками выбранной национальности. Процедура, которая называется Customer_Insert, принимает четыре параметра: newname (имя нового клиента), newareacode (код региона), newphone (телефон) и artistnationality (национальность художника). Ключевое слово IN указывает на то, что вес эти параметры являются входными. Выходные параметры обозначаются ключевым словом OUT, а параметры, играющие роль и входных, и выходных, — сочетанием IN OUT. Для параметра указывается тип данных, но не длина. Oracle определит длину из контекста.
Создадим файл Customer_Insert.sql, в котором пропишем процедуру
CREATE OR REPLACE PROCEDURE CustomerInsert
(
newname IN char,
newareacode IN char,
newphone IN char,
artistnationality IN char
)
AS
rowcount integer(4);
CURSOR artistcursor IS
SELECT ArtistID
FROM ARTIST
WHERE Nationality=artistnationality;
BEGIN
SELECT Count (*) INTO rowcount
FROM CUSTOMER
WHERE Name=newnaine AND Area_Code=newareacode AND Phone_Number=newphone;
IF rowcount > 0 THEN
BEGIN
DBMS_OUTPUT.PUT_LINE ('Клиент уже есть в базе данных - никаких действий не предпринято');
RETURN;
END;
END IF;
INSERT INTO CUSTOMER
(CustomerID,Name,Area_Code,Phone_Number)
VALUES
(CustID.NextVal,newname,newareacode,newphone);
FOR artist IN artistcursor
LOOP
INSERT INTO CUSTOMER_ARTIST_INT(CustomerID,ArttstID)
VALUES
(CustID.CurrVal,artist.ArtistID);
END LOOP;
DBMS_OUTPUT.PUT_LINE (‘ Новый клиент успешно добавлен в базу ');
END;
/
Создадим файл NewCustomerWithTransaction.sql, в котором пропишем хранимую процедуру, реализующую процесс создания представления
CREATE OR REPLACE PROCEDURE NewCustomerWithTransaction
(
newname IN char,
newareacode IN char,
newphone IN char,
artistname IN char,
worktitle IN char,
workcopy IN char,
price IN number
)
AS
rowcount integer(2);
tid int;
aid int;
CURSOR transcursor IS SELECT TransactionID,ARTIST.ArtistID FROM ARTIST,WORK,TRANSACTION WHERE
Name=artistname AND Title=worktitle AND Copy=workcopy AND
TRANSACTION.CustomerID IS NULL AND ARTIST.ArtistID=WORK.ArtistID AND WORK.WorkID=TRANSACTION.WorkID;
BEGIN
SELECT Count(*) INTO rowcount
FROM CUSTOMER WHERE Name=newname AND Area_Code=newareacode AND Phone_Number=newphone;
IF rowcount > 0 THEN
BEGIN
DBMS_OUTPUT.PUT_LINE('Customer Already Exists, changes denied');
RETURN;
END;
END IF;
INSERT INTO CUSTOMER(CustomerID,Name,Area_Code,Phone_Number) VALUES(CustID.NextVal,newname,newareacode,newphone);
rowcount:=0;
FOR trans In transcursor LOOP
tid :=trans.TransactionID;
aid :=trans.ArtistID;
rowcount:=rowcount+1;
END LOOP;
IF rowcount > 1 THEN
BEGIN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('Wrong records in ARTIST/WORK/TRANSACTION, changes denied');
RETURN;
END;
END IF;
IF rowcount=0 THEN
BEGIN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('There are no available lines in TRANSACTION, changes denied');
RETURN;
END;
END IF;
DBMS_OUTPUT.PUT_LINE(tid);
UPDATE TRANSACTION SET CustomerID=CustID.CurrVal, Salesprice=price, PurchaseDate=SysDate WHERE TransactionID=tid;
DBMS_OUTPUT.PUT_LINE('Client successfully added');
INSERT INTO CUSTOMER_ARTIST_INT(ArtistID,CustomerID) VALUES (aid,CustID.CurrVal);
END;
/
Логика этой процедуры, носящей имя NewCustomerWithTransaction, такова. Сначала создаются данные нового клиента, и в таблице TRANSACTION, где регистрируются купленные произведения, ведется поиск строк, и которых столбец CustomerID имеет пустое значение. Этот поиск ведется по соединению таблиц ARTIST, WORK и TRANSACTION, так как имя художника (Name) хранится в таблице ARTIST, а название произведения (Title) и номер копии (Copy) хранятся в таблице WORK. Если найдена ровно одна такая строка, в ней обновляются столбцы CustomerID (идентификатор клиента), SalesPrice (цена продажи) и PurchaseDate (дата приобретения). Затем добавляется запись в таблицу пересечения, чтобы зарегистрировать интерес клиента к данному художнику. В противном случае, если число найденных строк больше или меньше 1, никаких изменений в базе данных не производится.
Параметры процедуры NewCustomerWithTransaction содержат информацию о клиенте и приобретенном произведении. В процедуре объявлены несколько переменных и курсор. Курсор определен на соединении таблиц ARTIST, 41
WORK и TRANSACTION, Он выделяет столбцы TransactionID и ARTIST. ArtistID из строк, содержащих данные об искомом художнике и произведении и имеющих нулевое значение столбца CustomerID.
Прежде всего процедура выполняет проверку, нет ли уже в базе данных информации о данном клиенте. Если нет, данные нового клиента добавляются в базу. В PL/SQL нет оператора BEGIN TRANSACTION1 — первое действие с базой данных автоматически начинает транзакцию. Здесь новая транзакция начнется при добавлении данных о покупателе.
После того как данные о новом покупателе добавлены в базу, обрабатывается курсор TransCursor. Переменная rowcount используется для подсчета строк, в переменную tid записывается значение TransactionID, а в переменную aid — значение ArtistID. Заметьте, что оператор присваивания в Oracle выглядит так: «:=». Например, tid := trans.transactionID обозначает, что в переменную tid записывается значение trans.TransactionID.
В соответствии с логикой процедуры, если найдена одна и только одна строка, удовлетворяющая критериям, то в переменных tid и aid будут содержаться значения, нужные нам для успешного завершения транзакции. Если же таких строк не найдено или найдено более одной, то транзакция будет прервана, и ни tid, ни aid не будут использованы.
Для подсчета строк мы могли бы использовать выражение Count(*), и затем, если Count(*) = 1, запустить другой оператор, который бы получал нужные нам значения aid и tid. При той логике, которая реализована и листинге 2, необходимость во втором SQL-операторе отпадает.
Если число строк RowCount больше единицы или равно нулю, то выдается сообщение об ошибке и выполняется откат транзакции, отменяющий вставку данных в таблицу CUSTOMER. Если RowCount равно 1, обновляется соответствующая строка в таблице TRANSACTION. Обратите внимание на использование функции SysDate, с помощью которой записывается текущая дата. Наконец, в таблицу пересечения добавляется строка с информацией о покупателе и авторе купленного произведения (aid).
Зпустим хранимую процедуру
Создадим процедуру Select1.sql
SELECT CUSTOMER.Name, Copy, Title, ARTIST.Name
FROM CUSTOMER, TRANSACTION, WORK, ARTIST
WHERE CUSTOMER.CustomerID = TRANSACTION.CustomerID AND
TRANSACTION.WorkID = WORK.WorkID AND
WORK.ArtistID = ARTIST.ArtistID;
Создадим процедуру Select2.sql
SELECT CUSTOMER.Name, ARTIST.Name
FROM CUSTOMER, CUSTOMER_ARTIST_INT,ARTIST
WHERE CUSTOMER.CustomerID = CUSTOMER_ARTIST_INT.CustomerID
AND
ARTIST.ArtistID = CUSTOMER_ARTIST_INT.ArtistID;
Запустим эти две процедуры
Задания к лабораторной работе.
-
Модифицируйте процедуру 1, обеспечив добавление всех данных о новых покупателях, с учетом их интереса к художникам определенных национальностей.
CREATE OR REPLACE PROCEDURE CustomerInsert
(
newname IN char,
newstreet in char,
newcity in char,
newstate in char,
newZIP in char,
newareacode IN char,
newphone IN char,
artistnationality IN char
)
AS
rowcount integer(4);
CURSOR artistcursor IS SELECT ArtistID FROM ARTIST WHERE
Nationality=artistnationality;
BEGIN
SELECT Count(*) INTO rowcount
FROM CUSTOMER WHERE Name=newname AND Area_code=newareacode AND Phone_Number=newphone AND State=newstate AND City = newcity;
IF rowcount > 0 THEN
BEGIN
DBMS_OUTPUT.PUT_LINE('Client already exists, changes denied');
RETURN;
END;
END IF;
INSERT INTO CUSTOMER (CustomerID,Name, Street, City, State, ZIP,Area_Code,Phone_Number) Values (CustID.NextVal,newname,newstreet,newcity,newstate,newZIP,newareacode,newphone);
FOR artist IN artistcursor LOOP
INSERT INTO CUSTOMER_ARTIST_INT(CustomerID,ArtistID) VALUES
(CustID.CurrVal,artist.ArtistID);
END LOOP;
DBMS_OUTPUT.PUT_LINE('New client successfully added');
END;
/
-
Добавьте 2 новых покупателей (вызов процедуры 1)
-
Добавить в таблицу CUSTOMER новое поле Second_Name
-
Модифицируйте процедуру 2
CREATE OR REPLACE PROCEDURE NewCustomerWithTransaction
(
newname IN char,
newstreet in char,
newcity in char,
newstate in char,
newZIP in char,
newareacode IN char,
newphone IN char,
newsecondname IN char,
artistname IN char,
worktitle IN char,
workcopy IN char,
price IN number
)
AS
rowcount integer(2);
tid int;
aid int;
CURSOR transcursor IS SELECT TransactionID,ARTIST.ArtistID FROM ARTIST,WORK,TRANSACTION WHERE
Name=artistname AND Title=worktitle AND Copy=workcopy AND
TRANSACTION.CustomerID IS NULL AND ARTIST.ArtistID=WORK.ArtistID AND WORK.WorkID=TRANSACTION.WorkID;
BEGIN
SELECT Count(*) INTO rowcount
FROM CUSTOMER WHERE Name=newname AND Area_Code=newareacode AND Phone_Number=newphone;
IF rowcount > 0 THEN
BEGIN
DBMS_OUTPUT.PUT_LINE('Customer Already Exists, changes denied');
RETURN;
END;
END IF;
INSERT INTO CUSTOMER (CustomerID,Name, Street, City, State, ZIP,Area_Code,Phone_Number, Second_Name) Values (CustID.NextVal,newname,newstreet,newcity,newstate,newZIP,newareacode,newphone, newsecondname);
rowcount:=0;
FOR trans In transcursor LOOP
tid :=trans.TransactionID;
aid :=trans.ArtistID;
rowcount:=rowcount+1;
END LOOP;
IF rowcount > 1 THEN
BEGIN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('Wrong records in ARTIST/WORK/TRANSACTION, changes denied');
RETURN;
END;
END IF;
IF rowcount=0 THEN
BEGIN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('There are no available lines in TRANSACTION, changes denied');
RETURN;
END;
END IF;
DBMS_OUTPUT.PUT_LINE(tid);
UPDATE TRANSACTION SET CustomerID=CustID.CurrVal, Salesprice=price, PurchaseDate=SysDate WHERE TransactionID=tid;
DBMS_OUTPUT.PUT_LINE('Client successfully added');
INSERT INTO CUSTOMER_ARTIST_INT(ArtistID,CustomerID) VALUES (aid,CustID.CurrVal);
END;
/
-
Добавьте 2-х новых покупателей (вызов процедуры 2)