ПБД (9) - Лекция №8 - OQL: различия между версиями

Материал из Кафедра ИУ5 МГТУ им. Н.Э.Баумана, студенческое сообщество
Перейти к навигации Перейти к поиску
мНет описания правки
 
Строка 210: Строка 210:


=== Запросы на OQL ===
=== Запросы на OQL ===
 
Связь М-М, все актеры, которые снимались в фильме:
<syntaxhighlight lang="mysql">
<syntaxhighlight lang="mysql">
SELECT f.title
SELECT a.fio
FROM EF f, f.acts a
FROM EF f, f.acts a
WHERE a.fio="Иванов" AND f.year < 1950
WHERE f.title="Иванов" AND f.year < 1950
 
</syntaxhighlight>
<syntaxhighlight lang="mysql">
SELECT a.fio, a.addr
SELECT a.fio, a.addr
FROM EA a
FROM EA a
Строка 221: Строка 222:
</syntaxhighlight>
</syntaxhighlight>


и другие. Много.
Коллекция - элемент, множество связанных объектов и вложенный подзапрос.
Пример с группировкой:
 
<syntaxhighlight lang="mysql">
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
</syntaxhighlight>
PARTITION - результат группировки, коллекция всех объектов, которые попали в отдельную группу.
Здесь st и f.
WHERE работает до группировки.
HAVING накладывает ограничения на группы. Если он есть, то выполняется 4-ым шагом ( до SELECT'а).
<syntaxhighlight lang="mysql">
HAVING MIN(SELECT p.f.len FROM PARTITION P)>60.
</syntaxhighlight>
 
Сортировка:
<syntaxhighlight lang="mysql">
ORDER BY ASC st, year
</syntaxhighlight>
 
==== Агрегаты ====
<syntaxhighlight lang="mysql">
COUNT() - Для любых
MIN() - для подлежащих сортировке
SUM() - только для числовых
AVG() - только для числовых
MAX() - для подлежащих сортировке
</syntaxhighlight>
 
Можно применять к коллекции:
<syntaxhighlight lang="mysql">
COUNT(EF) - кол-во элементов в экстенте.
</syntaxhighlight>
 
 
Поддерживаются кванторы:
<syntaxhighlight lang="mysql">
SELECT a
FROM EA a
WHERE FOR ALL F IN a.films:F.st.name="ЛенФильм" AND f.year=2016
</syntaxhighlight>
 
<syntaxhighlight lang="mysql">
FOR ALL IN - квантор всеобщности
</syntaxhighlight>
 
<syntaxhighlight lang="mysql">
SELECT a
FROM EA a
WHERE EXISTS f1 IN a.films:f.yaer<2000
</syntaxhighlight>
 
Запрос на единственность:
<syntaxhighlight lang="mysql">
SELECT s
FROM ES s
WHERE COUNT(s.fms)=1
Те студии, которые сняли только один фильм.
</syntaxhighlight>
 
По умолчанию возвращается мультимножество структур.
<syntaxhighlight lang="mysql">
SELECT a.fio, f.year
Bag<struct{struct{f, i, o}, integer year}>
</syntaxhighlight>
 
Если хочется SET:
<syntaxhighlight lang="mysql">
SELECT DISTINCT
</syntaxhighlight>
Если хочется LIST:
<syntaxhighlight lang="mysql">
ORDER BY
</syntaxhighlight>
 
Можно и свою коллекцию:
<syntaxhighlight lang="mysql">
SELECT struct(fam:a.fio.f, yearMade:f.year)
Если поле одно, то структура не формируется.
</syntaxhighlight>
 
 
<syntaxhighlight lang="mysql">
(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
</syntaxhighlight>


[[Категория:Постреляционные базы данных (9 семестр)]]
[[Категория:Постреляционные базы данных (9 семестр)]]
[[Категория:Конспекты лекций и семинаров]]
[[Категория:Конспекты лекций и семинаров]]

Текущая версия от 14:12, 2 ноября 2016

Этот конспект ещё не дописан.
Здесь не хватает:
   - примеров запросов на языке 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