ПБД (9) - Лекция №8 - OQL
Этот конспект ещё не дописан. Здесь не хватает: - примеров запросов на языке OQL. |
Содержание
SQL
Пользовательские типы данных
User Defined Types - UDT.
Создаём свой тип:
CREATE TYPE Addr AS ( city CHAR(20), street VARCHAR(100) ) -- объявление метода method fullad() RETURNS VARCHAR(130); -- определение метода CREATE method fullad() RETURNS VARCHAR(130) FOR Addr BEGIN RETURN SELF.city || SELF.street END;
Используем его при описании других:
CREATE TYPE Studia AS ( sname VARCHAR(50), addr Addr ); CREATE TYPE Actor AS ( inn INT, fio VARCHAR(50), addr Addr );
Создаём таблицы со ссылками:
CREATE TABLE Tact OF Actor ( PRIMARY KEY (inn), REF IS Ida system generated ); CREATE TABLE TSt ( REF IS Ids system generated )
Создаём тип со ссылками:
CREATE TYPE Film AS ( title VARCHAR(80), YEAR unt, len INT, TYPE CHAR(2), st REF(Studia) [SCOPE TSt] -- SCOPE показывает, что это на конкретную талицу );
Ещё таблицы:
CREATE TABLE FA ( act REF(Actor) SCOPE TAct, film REF(Film) SCOPE TF ); CREATE TABLE TF OF Film ( REF IS Idf system generated );
Запросы к UDT
-- один ко многим SELECT YEAR, len st->sname, st->addr.city, st->addr.fullad() FROM TF WHERE title = 'The Matrix' -- многие ко многим (обращение к одной таблице, которая её реализует) SELECT film->title, film->YEAR, film->st->name FROM FA WHERE act->fio='Иванов' -- разыменование ссылок SELECT deref(act) FROM FA WHERE film->title='The Matrix' -- выведет всех актёров этого фильма
Методы
Создаются системой автоматически.
Методы обозреватели
Они же getter
. Совпадают с названием поля, не имеют параметров. Нужны для получения значений полей.
SELECT f.title(), f.len() FROM TF WHERE f.type='BW'
Методы модификаторы
Они же setter
. Для изменения значения полей.
Методы генераторы
Они же конструкторы.
DECLARE newA Addr; DECLARE newS Stud; SET newA = Addr(); -- вызов конструктора newA.city('Москва'); newA.street('Ленина, 2'); SET newS = Studia(); -- вызов конструктора newS.sname('Мосфильм'); news.addr(newA); INSERT INTO TSt VALUES(newS);
Сравнение типов
CREATE ORDERING FOR Addr <EQUALS ONLY | ORDER FULL | RELATIVE WITH f> BY STATE -- f - это функция, выполняющая сравнение двух параметров -- она не стандартная, её надо создать CREATE FUNCTION f(x1 Addr, x2 Addr) RETURNS INT IF x1.city > x2.city TNEN RETURN 1; ELSE IF x1.city < x2.city TNEN RETURN -1; ELSE IF x1.street > x2.street TNEN RETURN 1; ELSE IF x1.street < x2.street TNEN RETURN -1; ELSE RETURN 0; END IF;
Производные типы
CREATE TYPE имя UNDER базовый тип AS ( поле тип, ... [[NOT] instantiable] -- можно ли на его основе создать ещё тип [NOT] final -- можно ли его переопределять <REF IS system generated | REF USING тип | REF USING (атрибут)> ); [overriding] [<instance | static | constructor>] method название(параметры) RETURNS тип [SELF AS <RESULT | locator>] [parameter STYLE <SQL | Java | ...>] [[NOT] deteministic] [no SQL | contains SQL | ...] [RETURN <NULL ON NULL INPUT | called ON NULL input>]
OQL
Object Query Language.
class Film(extent EF) { attribute string title; attribute string year; attribute string len; attribute string type; relationship Stud st inverse Stud::fl; relationship set <Actor> acts inverse Actor::films; set <Stud> StofFl(); -- метод int firstFilm(); } class Actor(extent EA) { attribute string fio; attribute int inn; relationship set <Film> films inverse ... ; -- атрибут-структура attribute Struct{string city, string street} addr; }
Запросы на OQL
Связь М-М, все актеры, которые снимались в фильме:
SELECT a.fio FROM EF f, f.acts a WHERE f.title="Иванов" AND f.year < 1950
SELECT a.fio, a.addr FROM EA a WHERE for all f in a.films : f.st.sname="Мосфильм"
Коллекция - элемент, множество связанных объектов и вложенный подзапрос. Пример с группировкой:
4 SELECT st, y , sumlen: sum(SELECT P.f.len FROM PARTITION P) 1 FROM ES st, st.fms F 2 WHERE f.year>2000 3 GROUP BY st:st.name, y:f.year
PARTITION - результат группировки, коллекция всех объектов, которые попали в отдельную группу. Здесь st и f. WHERE работает до группировки. HAVING накладывает ограничения на группы. Если он есть, то выполняется 4-ым шагом ( до SELECT'а).
HAVING MIN(SELECT p.f.len FROM PARTITION P)>60.
Сортировка:
ORDER BY ASC st, year
Агрегаты
COUNT() - Для любых MIN() - для подлежащих сортировке SUM() - только для числовых AVG() - только для числовых MAX() - для подлежащих сортировке
Можно применять к коллекции:
COUNT(EF) - кол-во элементов в экстенте.
Поддерживаются кванторы:
SELECT a FROM EA a WHERE FOR ALL F IN a.films:F.st.name="ЛенФильм" AND f.year=2016
FOR ALL IN - квантор всеобщности
SELECT a FROM EA a WHERE EXISTS f1 IN a.films:f.yaer<2000
Запрос на единственность:
SELECT s FROM ES s WHERE COUNT(s.fms)=1 Те студии, которые сняли только один фильм.
По умолчанию возвращается мультимножество структур.
SELECT a.fio, f.year Bag<struct{struct{f, i, o}, integer year}>
Если хочется SET:
SELECT DISTINCT
Если хочется LIST:
ORDER BY
Можно и свою коллекцию:
SELECT struct(fam:a.fio.f, yearMade:f.year) Если поле одно, то структура не формируется.
(SELECT a FROM EA a, a.films f WHERE f.stud.name="МосФильм") EXCEPT (SELECT a FROM EA a, EF f WHERE f.stud.name="Экран") Аналогично можно с UNION и INTERSECT