Слайд 1Базы данных
Язык запросов SQL. Команда SELECT
Слайд 2Команда SELECT – выборка данных
Общий синтаксис:
SELECT [{ ALL | DISTINCT }]
{ список_вывода | * }
FROM имя_таблицы1 [ алиас1 ] [, имя_таблицы2 [ алиас2 ].,..]
[ WHERE условие_отбора_записей ]
[ GROUP BY { имя_поля | выражение }.,..
[ HAVING условие_отбора_групп ]
[ UNION [ALL] SELECT …]
[ ORDER BY имя_поля1 [ ASC | DESC ]
[, имя_поля2 [ ASC | DESC ].,..]];
Примеры:
select * from departs;
select name, post from emp;
Слайд 3Формирование списка вывода (проекция)
Общий синтаксис списка вывода:
[{all | distinct}] { *
| выражение1 [алиас1] [, выражение2 [алиас2] .,..]}
Список ввода находится между ключевыми словами SELECT и FROM.
Вывести все поля всех записей из таблицы Проекты (Project):
select * from project;
Вывести список сотрудников с указанием их должности и № отдела:
select depno, name, post
from emp;
Вывести список сотрудников с указанием их должности и зарплаты:
select name "ФИО", post "Должность", salary*0.87 "Зарплата"
from emp;
Слайд 4Формирование списка вывода (проекция)
Вывести должности и оклады сотрудников:
select post, salary
from
emp;
Вывести должности и оклады сотрудников без повторов:
select DISTINCT post, salary
from emp;
Вывести отделы и должности сотрудников без повторов:
select DISTINCT depno, post
from emp;
Задание: вывести список сотрудников с указанием ФИО, даты рождения и адреса.
select name "ФИО", born "Дата рождения", adr "Адрес"
from emp;
Слайд 5Упорядочение результата
Вывести данные из таблицы Проекты в порядке даты начала проекта:
select
*
from Project
order by dbegin;
Упорядочить список сотрудников по отделам и по ФИО:
select depno, name, post
from emp
order by depno, name; -- order by 1,2;
Упорядочить сотрудников по зарплате (от большей к меньшей):
select name 'ФИО', post 'Должность', salary 'Зарплата'
from emp
order by 3 DESC;
Упорядочить данные об отделах, должностях и зарплатах:
select depno 'Номер отдела', post 'Должность', salary 'Зарплата'
from emp
order by 1, 3 DESC, 2;
Слайд 6Выбор данных из таблицы (селекция)
WHERE – содержит условия выбора отдельных записей. Условие является
логическим выражением и может принимать одно из 3-х значений:
TRUE – истина,
FALSE – ложь,
NULL – неизвестное, неопределённое значение (интерпретируется как ложь).
Условие формируется путём применения различных операторов и предикатов. Операторы сравнения:
= – равно, <>, != – не равно, > – больше, < – меньше,
>= – больше или равно, <= – меньше или равно.
Вывести список сотрудников 2-го отдела:
select * from emp
where depno = 2;
Вывести список текущих проектов:
select * from project
where dend > Getdate();
-- Getdate() – функция, возвращающая текущую дату
Слайд 7Логические операторы
Для формирования условий используются следующие логические операторы:
AND – логическое произведение
(И),
OR – логическая сумма (ИЛИ),
NOT – отрицание (НЕ).
Операция И: Операция ИЛИ:
Операция НЕ:
Слайд 8Выбор данных из таблицы по условию
Вывести список сотрудников 2-го отдела с
зарплатой больше 30000 рублей:
select * from emp
where depno = 2 AND salary > 30000 ;
Вывести список сотрудников-мужчин, родившихся после 1979 года:
select * from emp
where born > '31/12/1979' AND sex = 'м';
Вывести список сотрудников 2-го и 5-го отделов:
select * from emp
where depno=2 OR depno = 5;
Вывести список сотрудников 2-го и 5-го отделов в зарплатой не менее 30000:
select * from emp
where (depno=2 OR depno = 5) AND salary >= 30000 ;
Вывести список всех сотрудников, кроме сотрудников 2-го и 5-го:
select * from emp
where NOT (depno=2 OR depno = 5);
Слайд 9Выбор данных из таблицы по условию
Задание 1: вывести список текущих проектов
стоимостью более 2 млн. рублей.
select *
from project
where dend > GetDate()AND cost > 2000000;
Задание 2: вывести список сотрудников, работающих в должностях 'инженер' и 'ведущий инженер'.
select *
from emp
where post = 'инженер' OR post = 'ведущий инженер' ;
Задание 3: вывести список сотрудников, работающих в должности 'охранник', с зарплатой более 20000 рублей.
select *
from emp
where post = 'охранник' AND salary > 20000;
Слайд 10Предикаты формирования условия
Предикат вхождения в список значений:
имя_поля IN ( значение1 [,
значение2,... ] )
выражение IN ( значение1 [, значение2,... ] )
Примеры:
Список сотрудников отделов 5, 8 и 9:
select *
from emp
where depno IN ( 5, 8, 9 ) ;
Список сотрудников, работающих в должностях 'инженер' и 'ведущий инженер' :
select *
from emp
where post IN ( 'инженер', 'ведущий инженер' );
Слайд 11Предикаты формирования условия
Предикат вхождения в диапазон:
имя_поля BETWEEN минимальное_значение AND
максимальное_значение
выражение BETWEEN минимальное_значение AND максимальное_значение
Минимальное значение должно быть меньше либо равно максимальному.
Примеры:
Список всех сотрудников со 2-го по 5-й отделы:
select *
from emp
where depno BETWEEN 2 AND 5 ;
Список сотрудников зарплатой от 20 до 30 тысяч рублей:
select *
from emp
where salary BETWEEN 20000 AND 30000;
Слайд 12Предикаты формирования условия
Предикат поиска подстроки: имя_поля LIKE 'шаблон'
Этот предикат применяется только
к полям типа CHAR и VARCHAR. Возможно использование шаблонов:
'_' – один любой символ,
'%' – произвольное количество символов любых символов (в т.ч., ни одного).
Примеры:
Список всех сотрудников-экономистов:
select * from emp
where post LIKE '%экономист%' ;
Список всех инженеров-специалистов (кроме просто инженеров):
select * from emp
where post LIKE 'инженер_%' ;
Слайд 13Предикаты формирования условия
Предикат поиска неопределенного значения:
значение IS [NOT] NULL
Если значения
является неопределенным (NULL), то предикат IS NULL выдаст истину, а предикат IS NOT NULL – ложь.
Примеры:
Список всех сотрудников, у которых нет телефона (номер телефона неопределен):
select *
from emp
where phone IS NULL ;
Список все проекты, у которых определена стоимость:
select *
from project
where cost IS NOT NULL ;
Слайд 14Использование предикатов
Задание 1: вывести список сотрудников, которых зовут 'ЮРИЙ'.
select *
from emp
where name LIKE '%ЮРИЙ%';
Задание 3: вывести список сотрудников, которые являются начальниками отделов.
select *
from emp
where post LIKE 'нач%отдел%';
Задание 2: вывести список проектов стоимостью от 1 до 2 млн. рублей.
select *
from project
where cost BETWEEN 1000000 AND 2000000;
Слайд 15Агрегирующие функции
COUNT – подсчёт количества строк (значений). Применяется к записям и полям любого
типа. Имеет 3 формата вызова:
count (*) – количество строк результата;
count (имя_поля) – количество значений указанного поля, не являющихся NULL-значениями.
count (distinct имя_поля) – количество разных не-NULL значений
указанного поля.
MAX, MIN – определяет максимальное (минимальное) значение указанного поля в результирующем множестве. Применяется к полям любого типа.
SUM – определяет арифметическую сумму значений указанного числового поля в результирующем множестве записей.
AVG – определяет среднее арифметическое значений указанного числового поля в результирующем множестве записей. Не учитывает NULL-значения, и сумма значений поля делится на количество определённых значений.
Слайд 16Примеры использования функции COUNT
Вывести количество сотрудников:
select count(*)
from emp;
Вывести количество сотрудников
с телефонами:
select count( phone )
from emp;
Вывести количество разных должностей сотрудников:
select count (DISTINCT post)
from emp;
Задание: вывести количество сотрудников 6-го отдела.
select count(*)
from emp
where depno = 6;
Слайд 17Примеры использования агрегирующих функций
Вывести максимальную и минимальную стоимость проектов:
select max(cost) "Максимальная
цена", min(cost) "Минимальная цена"
from project;
Вывести сумму зарплаты сотрудников 8-го отдела:
select sum(salary)
from emp
where depno = 8;
Вывести среднюю зарплату сотрудниц предприятия:
select avg(salary)
from emp
where sex = 'Ж';
Вывести даты начала работы над первым проектом и завершения работы над последним проектом:
select min(dbegin), max(dend)
from project;
Слайд 18Группировка данных: предложение GROUP BY
Агрегирующие функции обычно используются совместно с предложением
GROUP BY.
Например, следующая команда считает количество сотрудников по отделам:
select depno, count(*)
from emp
group by depno;
Слайд 19Примеры использования GROUP BY
Вывести минимальную и максимальную зарплату в каждом отделе:
select depno, MIN(salary) minsal, MAX(salary) maxsal
from emp
group by depno;
Вывести количество разных должностей в каждом отделе:
select depno, COUNT(distinct post) cnt
from emp
group by depno;
Посчитать сумму зарплат в каждом отделе:
select depno, SUM(salary) allsal
from emp
group by depno;
Посчитать среднюю зарплату по каждой должности:
select post, AVG(salary) avgsal
from emp
group by post;
Слайд 20Использование GROUP BY
Правило использования GROUP BY :
В списке вывода при использовании GROUP BY
могут быть указаны только функции агрегирования, константы и поля, перечисленные в GROUP BY.
Если включить в список выбора поля, не указанные в GROUP BY, то СУБД не будет выполнять такой запрос и выдаст ошибку "нарушение условия группирования" (not a GROUP BY expression).
Например, нельзя получить сведения о том, у каких сотрудников самая высокая зарплата в своём отделе с помощью такого запроса:
select depno, name, max(salary) as max_sal
from emp
group by depno;
Этот запрос синтаксически неверен!
Слайд 21Группировка по нескольким полям
Сумма зарплаты по отделам и по должностям:
select depno, post, count(*), sum(salary)
from emp
group by depno, post;
Количество мужчин и женщин по отделам:
select depno, sex, count(*)
from emp
group by depno, sex;
Задание: вывести информацию о зарплате и количестве сотрудников, которые получают такую зарплату.
select salary, count(*)
from emp
group by salary;
Слайд 22Использование фразы HAVING
Если необходимо вывести не все записи, полученные в результате
группировки (GROUP BY), то условие на группы можно указать во фразе HAVING (но не во фразе WHERE).
Пример. Список отделов, в которых работает больше пяти человек:
select depno, count(*), 'человек(а)'
from emp
group by depno
having count(*)>5;
Правило: нельзя указывать агрегирующие функции в части WHERE –
это синтаксическая ошибка!
Задание: вывести список отделов, в которых средняя зарплата больше 30000
рублей.
select depno, avg(salary)
from emp
group by depno
having avg(salary) > 30000;
Слайд 23Операции реляционной алгебры
Унарные операции:
селекция – выбор из таблицы подмножества строк по
условию.
Например, список сотрудников 5-го отдела:
select *
from emp
where depno = 5;
проекция – выбор из таблицы подмножества столбцов.
Например, сведения о должности и зарплате сотрудников:
select distinct name, post, salary
from emp;
Слайд 24Бинарные операции реляционной алгебры
Бинарные операции РА:
разносхемные – применяются к любым двум
отношениям.
односхемные – применяются к односхемным отношениям. Исходные отношения должны иметь одинаковое количество столбцов одинаковых (или сравнимых) типов. Сравнимыми считаются типы, относящиеся к одному и тому же семейству данных (в таблице полужирным шрифтом выделены базовые типы).
Семейства типов данных Oracle:
Слайд 25Бинарные односхемные операции РА
Объединение двух односхемных отношений содержит все строки исходных
отношений без повторов.
Разность двух односхемных отношений содержит все строки первого отношения, не входящие во второе отношение (без повторов).
Пересечение двух односхемных отношений содержит все строки, входящие и в первое, и во второе отношения (без повторов).
Добавим в нашу БД проектной организации таблицу "Архив должностей":
create table archive (
tabno number(6) REFERENCES emp, -- ссылка на сотрудника
name varchar2(100) not null, -- ФИО сотрудника
dbegin date not null, -- начало работы в должности
post varchar(50) not null -- должность
);
Слайд 26Операция объединения
Объединение реализуется с помощью специального ключевого слова UNION (или UNION
ALL, если не нужно удалять повторы).
Примеры:
Список сотрудников с телефонами или адресами (если нет телефона):
select depno, name, PHONE
from emp where phone is not null
UNION ALL
select depno, name, ADR
from emp where phone is null;
Список сотрудников со всеми переводами с одной должности на другую:
select tabno, name, edate, post
from emp
UNION ALL
select tabno, name, dbegin, post
from archive
order by 1, 3;
Слайд 27Разность отношений
Разность в Oracle реализуется с помощью специального ключевого слова MINUS.
Примеры:
Список
сотрудников 5-го и 8-го отделов, которые не являются инженерами:
select * from emp
where depno IN (5, 8)
MINUS
select * from emp
where post LIKE '%инженер%'
order by depno;
Список сотрудников, которые не переводились на другие должности:
select tabno, name
from emp
MINUS
select tabno, name
from archive;
Слайд 28Пересечение отношений
Переcечение в Oracle реализуется с помощью специального ключевого слова INTERSECT.
Примеры:
Список
сотрудников 5-го и 8-го отделов, которые являются инженерами:
select * from emp
where depno IN (5, 8)
INTERSECT
select * from emp
where post LIKE '%инженер%'
order by depno;
Список сотрудников, которые переводились на другие должности:
select tabno, name
from emp
INTERSECT
select tabno, name
from archive;
Слайд 29Применение односхемных операций РА
Задание 1: вывести список должностей, которые занимают (или
занимали) сотрудники.
select post from emp
UNION
select post from archive;
Задание 3: вывести список должностей, которые в настоящее время не занимает ни один сотрудник.
select post from archive
MINUS
select post from emp;
Задание 2: вывести список должностей, на которые переназначены другие сотрудники.
select post from emp
INTERSECT
select post from archive;
Слайд 30Разносхемные операции РА
Декартово произведение (ДП): операция над двумя произвольными (возможно, разносхемными)
отношениями. Результат ДП – все комбинации строк исходных отношений. Пример:
Слайд 31Разносхемные операции РА
Пример декартова произведения реальных таблиц:
select *
from depart,
emp;
Если в части FROM указываются 2 и более таблицы, то СУБД по умолчанию строит их декартово произведение.
Другая разносхемная операция – соединение: селекция от декартова произведения.
Примеры.
1. Список отделов и их сотрудников:
select *
from depart, emp
where emp.depno = depart.did;
2. Список проектов и их участников:
select *
from project, emp, job
where emp.tabno = job.tabno
and job.pro = project.pro;
Слайд 32Применение операции соединения
Задание 1: вывести сотрудников с указанием ролей, которые они
исполняют в проектах.
select e.name, j.rel
from emp e, job j
where e.tabNo = j.tabNo;
Задание 2: вывести список проектов с указанием их руководителей.
select p.title, e.name
from emp e, job j, project p
where e.tabno = j.tabno
and j.pro = p.pro
and j.rel = 'руководитель';
Слайд 33Применение операции соединения
select name, count(*)
from emp, job
where emp.tabno=job.tabno
group by emp.tabno, emp.name;
Задание 3: вывести список сотрудников с указанием количества проектов, в которых они участвуют.
Задание 4: вывести список проектов, в которых участвует более 5 сотрудников.
select p.title, count(*)
from job j, project p
where p.pro = j.pro
group by p.pro, p.title
having count(*) > 5;
Слайд 34Общий алгоритм выполнения операции SELECT
Выбор записей из указанной таблицы (from).
Проверка для
каждой записи условия отбора (where).
Группировка полученных в результате отбора записей (group by) и вычисление для этих групп значений агрегирующих функций.
Выбор тех групп, которые удовлетворяют условию отбора групп (having).
Сортировка полученных записей в указанном порядке (order by).
Извлечение из полученных записей тех полей, которые заданы в списке вывода, и формирование результирующего отношения.
Если в части FROM указывается 2 и более таблицы, то приведенный алгоритм выполняется для декартова произведения этих таблиц.
Слайд 35Стандарты SQL
SQL (Structured Query Language) - Структурированный Язык Запросов - стандартный
язык запросов к реляционной базе данных.
Язык SQL появился после реляционной алгебры, и его прототип был разработан в конце 70-х годов в компании IBM Research.
SQL был реализован в первом прототипе реляционной СУБД фирмы IBM System R.
Первый международный стандарт языка SQL был принят в 1989 г.
(принято называть его SQL/89 или SQL1). Стандарт SQL1 также называют стандартом ANSI/ISO, и все СУБД поддерживают этот стандарт полностью.
Развитие информационных технологий, связанных с базами данных, и необходимость реализации переносимых приложений потребовали доработки и расширения первого стандарта SQL.
Слайд 36Стандарты языка SQL
В 1992 г. принят новый международный стандарт языка SQL,
который стали называть SQL/92 или SQL2.
В 1999 году появился новый стандарт, названный SQL3.
Если отличия между стандартами SQL1 и SQL2 были количественными, то стандарт SQL3 соответствует качественным преобразованиям.
В SQL3 введены новые типы данных, добавлен раздел стандартов на события и триггеры.
Слайд 37Триггеры в стандарте SQL
В стандарте определена спецификация триггеров как
совокупности события и действия.
В качестве действия выступают не только последовательность операторов SQL, но и операторы управления ходом выполнения программы.
В модели управления транзакциями появились точки сохранения (savepoints).
Возможность указания в операторе отката ROOLBACK точек возврата позволило откатывать транзакцию не в начало, а в промежуточную ранее сохраненную точку, что повысило гибкость реализации сложных алгоритмов обработки информации.
Слайд 38SQL – Structured Query Language
Стандарты SQL, определённые Американским национальным институтом стандартов
(ANSI):
SQL-1 (SQL/89) – первый вариант стандарта.
SQL-2 (SQL/92) – основной расширенный стандарт.
SQL-3 (SQL/1999, SQL/2003) – относится к объектно-реляционной модели данных.
Слайд 39Язык запросов SQL
SQL не относится к традиционным языкам программирования, содержащим операторы,
управляющие ходом выполнения программы, операторы описания типов.
SQL содержит только набор стандартных операторов доступа к данным, хранящимся в базе данных.
Операторы SQL встраиваются в базовый язык программирования, которым может быть любой стандартный язык типа C++, PL, COBOL и т. д.
Кроме того, операторы SQL могут выполняться непосредственно в интерактивном режиме.
Слайд 40Структура SQL
SQL является полным языком, в нем присутствуют не только операции
запросов, но и операторы, соответствующие DDL - Data Definition Language - языку описания данных.
Кроме того, язык содержит операторы, предназначенные для управления (администрирования ) базы данных.
Слайд 41SQL – Structured Query Language
Подмножества языка SQL:
DDL (Data Definition Language)
– команды создания/изменения/удаления объектов базы данных (create/alter/drop);
DML (Data Manipulation Language) – команды добавления/модификации/удаления данных (insert/update/delete), а также команда извлечения данных select;
DCL (Data Control Language) – команды управления данными (установка/снятие ограничений целостности). Входит в подмножество DDL.
Слайд 42Особенности синтаксиса SQL
В командах SQL не различаются прописные и строчные буквы
(кроме содержимого символьных строк).
Каждая команда может занимать несколько строк и заканчивается символом ';'.
Символ и символьная строка заключается в одинарные кавычки:
'А', '2' , 'строка', 'другая строка'
Однострочный комментарий начинается с символов '--'.
Многострочный комментарий заключается в символы /* ... */.
Слайд 44Команды DDL
CREATE – создание объекта.
ALTER – изменения структуры объекта.
DROP – удаление
объекта.
Общий вид синтаксиса команд DDL:
create
alter тип_объекта имя_объекта [параметры];
drop
Слайд 45Операторы манипулирования данными
Слайд 46Подмножество команд DML
INSERT – добавление строк в таблицу.
Добавляет одну или несколько
строк в указанную таблицу.
UPDATE – изменение данных.
Изменяет значения одного или нескольких полей в записях указанной таблицы.
Можно указать условие, по которому выбираются обновляемые строки.
Если условие не указано, обновляются все строки таблицы.
Если ни одна строка не удовлетворяет условию, ни одна строка не будет обновлена.
DELETE – удаление строк из таблицы.
Удаляет одну или несколько строк из таблицы.
Можно указать условие, по которому выбираются удаляемые строки.
Если условие не указано, удаляются все строки таблицы.
Если ни одна строка не удовлетворяет условию, ни одна строка не будет удалена.
Слайд 47Добавление данных
INSERT – добавление строк в таблицу:
INSERT INTO имя_таблицы [(список_полей_таблицы)]
{
VALUES (список_выражений) | запрос };
Примеры:
-- Добавить в таблицу "Отделы" новую запись (все поля):
insert into depart
values(7, 'Договорной отдел');
-- Добавить в таблицу "Сотрудники" новую запись (не все поля):
insert into emp (tabno, name, born, sex, depno, passport, pass_date_pass_get,
post, salary, phone)
values( 301, 'САВИН АНДРЕЙ ПАВЛОВИЧ', '11.07.1969',
'М', 5, '4405092876', '15.02.1999',
'ОВД "Митино" г.Москвы', 'программист', 38050, '121-34-11');
Слайд 48Изменение данных
UPDATE – изменение данных:
UPDATE имя_таблицы
SET имя_поля1 = выражение1 [,
имя_поля2 = выражение2,…]
[WHERE условие];
Примеры:
-- Изменить статус сотрудника Бобкова Л.П., табельный номер 74, по отношению к проекту 30."Система автоматизированного управления предприятием":
update job
set rel = 'консультант'
where tabno = 74 and pro = 30;
-- Перевести сотрудника Жаринова А.В., табельный номер 68, на должность ведущего программиста и повысить оклад на три тысячи рублей:
update emp
set post = 'ведущий программист', salary = salary+3000
where tabno = 68;
Слайд 49Удаление данных
DELETE – удаление строк из таблицы:
DELETE FROM имя_таблицы
[ WHERE условие
];
Примеры.
-- Удалить сведения о том, что сотрудник Афонасьев В.Н., табельный номер 147, участвует в проектах:
delete from job
where tabno=147;
-- Удалить сведения о сотруднике Афонасьеве В.Н., табельный номер 147:
delete from emp
where tabno = 147;
Замечание: отменить удаление данных можно командой
ROLLBACK;
Слайд 50Язык запросов Data Query Language (DQL)
Слайд 51Средства управления транзакциями
Слайд 52Средства администрирования данных
Слайд 56Типы данных
В языке SQL/89 поддерживаются следующие типы данных:
CHARACTER(n) или
CHAR(n) — символьные строки постоянной длины в n символов. При задании данного типа под каждое значение всегда отводится n символов, и если реальное значение занимает менее, чем n символов, то СУБД автоматически дополняет недостающие символы пробелами.
NUMERIC[(n,m)] — точные числа, здесь n — общее количество цифр в числе, m — количество цифр слева от десятичной точки.
DECIMAL[(n,m)] — точные числа, здесь n — общее количество цифр в числе, m — количество цифр слева от десятичной точки.
DEC[(n,m)] - то же, что и DECIMAL[(n,m)].
INTEGER или INT — целые числа.
SMALLINT — целые числа меньшего диапазона.
Тип данных INTEGER соответствует целым числам, хранимым в четырех байтах, a SMALLINT — соответствует целым числам, хранимым в двух байтах.
Слайд 57
FLOAT[(n)] — числа большой точности, хранимые в форме с плавающей
точкой. Здесь n — число байтов, резервируемое под хранение одного числа. Диапазон чисел определяется конкретной реализацией.
REAL — вещественный тип чисел, который соответствует числам с плавающей точкой, меньшей точности, чем FLOAT.
DOUBLE PRECISION специфицирует тип данных с определенной в реализации.
Слайд 58В стандарте SQL92 добавлены следующие типы данных:
VARCHAR(n) - строки символов
переменной длины.
NCHAR(N) - строки локализованных символов постоянной длины.
NCHAR VARYING(n) - строки локализованных символов переменной длины.
BIT(n) - строка битов постоянной длины.
BIT VARYING(n) - строка битов переменной длины.
DATE - календарная дата.
ТIMESТАМР(точность) - дата и время.
INTERVAL - временной интервал.
Все СУБД поддерживают тип данных для представления неструктурированного текста большого объема.
Этот тип аналогичен типу MEMO в настольных СУБД. Называются эти типы по-разному, например в ORACLE этот тип называется LONG, в DB2 - LONG VARCHAR, в SYBASE и MS SQL Server - TEXT.