|
| ||||||||||||
| ||||||||||||
|
2008 г.
Базы данных. Вводный курсСергей Кузнецов18.2.4. Предикат inПредикат позволяет специфицировать условие вхождения строчного значения в указанное множество значений. Синтаксические правила следующие:
in_predicate ::= row_value_constructor [ NOT ]
IN in_predicate_value
in_predicate_value ::= table_subquery
| (value_expression_comma_list)
Строка, являющаяся первым операндом, и таблица-второй операнд должны быть одинаковой степени. В частности, если второй операнд представляет собой список значений, то первый операнд должен иметь степень 1. Типы данных соответствующих столбцов операндов должны быть совместимы. Пусть По определению условие Примеры запросов с использованием предиката inПример 18.9. Найти номера, имена и номера отделов служащих, работающих в отделах 15, 17 и 19. SELECT EMP_NO, EMP_NAME, DEPT_NO FROM EMP WHERE DEPT_NO IN (15, 17, 19); Конечно, эта формулировка запроса эквивалентна следующей формулировке (пример 18.9.1): SELECT EMP_NO, EMP_NAME, DEPT_NO FROM EMP WHERE DEPT_NO = 15 OR DEPT_NO = 17 OR DEPT_NO = 19; Пример 18.10. Найти номера служащих, не являющихся руководителями отделов и получающих заплату, размер которой равен размеру зарплаты какого-либо руководителя отдела.
SELECT EMP_NO
FROM EMP
WHERE EMP_NO NOT IN (SELECT DEPT_MNG FROM DEPT)
AND EMP_SAL IN (SELECT EMP_SAL FROM EMP, DEPT
WHERE EMP_NO = DEPT_MNG);
Запросы, содержащие предикат SELECT DISTINCT EMP_NO FROM EMP, EMP EMP1, DEPT WHERE EMP_NO NOT IN (SELECT DEPT_MNG FROM DEPT) AND EMP_SAL = EMP1_SAL AND EMP1.EMP_NO = DEPT.DEPT_MNG; По поводу этой второй формулировки следует сделать два замечания. Во-первых, как видно, мы изменили только ту часть условия, в которой использовался предикат 18.2.5. Предикат likeФормально предикат
like_predicate ::= source_value [ NOT ]
LIKE pattern_value [ ESCAPE escape_value ]
source_value ::= value_expression
pattern_value ::= value_expression
escape_value ::= value_expression
Все три операнда ( Если обрабатываются символьные строки, и если раздел В случае обработки битовых строк сопоставление шаблона со строкой производится восьмерками соседних бит (октетами). В соответствии со стандартом SQL:1999, при сопоставлении шаблона со строкой производится специальная интерпретация октетов со значениями Значение предиката Примеры запросов с использованием предиката likeПример 18.11. Найти номера проектов, в названии которых присутствуют слова
SELECT PRO_TITLE
FROM PRO
WHERE PRO_TITLE LIKE '%next%step%'
OR PRO_TITLE LIKE 'Next%step%';
Это очень неудачный запрос, потому что его выполнение, скорее всего, вынудит СУБД просмотреть все строки таблицы SELECT PRO_TITLE FROM PRO WHERE PRO_TITLE LIKE '%ext%step%'; Пример 18.12. Найти номера отделов, служащие которых являются менеджерами проектов, и название каждого из этих проектов начинается с названия отдела. SELECT DISTINCT DEPT.DEPT_NO FROM EMP, DEPT, PRO WHERE EMP.EMP_NO = PRO.PRO_MNG AND EMP.DEPT_NO = DEPT.DEPT_NO AND PRO.PRO_TITLE LIKE DEPT.DEPT_NAME || '%'; Вот как может выглядеть формулировка этого запроса, если использовать вложенные подзапросы (пример 18.12.1):
SELECT DEPT.DEPT_NO
FROM DEPT
WHERE DEPT.DEPT_NO IN
(SELECT EMP.DEPT_NO
FROM EMP
WHERE EMP.EMP_NO IN
(SELECT PRO.PRO_MNG FROM PRO
WHERE PRO.PRO_TITLE LIKE DEPT.DEPT_NAME || '%'));
Пример 18.13. Найти номера отделов, названия которых не начинаются со слова 'Software'. SELECT DEPT_NO FROM DEPT WHERE DEPT_NAME NOT LIKE 'Software%'; 18.2.6. Предикат similarФормально предикат
similar_predicate ::= source_value [ NOT ]
SIMILAR TO pattern_value [ ESCAPE escape_value ]
source_value ::= character_expression
pattern_value ::= character_expression
escape_value ::= character_expression
Все три операнда ( Основное отличие предиката
regular_expression ::= regular_term
| regular_expression vertical_bar regular_term
regular_term ::= regular_factor
| regular_term regular_factor
regular_factor ::= regular_primary
| regular_primary *
| regular_primary +
regular_primary ::= character_specifier
| %
| regular_character_set
| ( regular_expression )
character_specifier ::= non_escape_character
| escape_character
regular_character_set ::= _
| left_bracket
character_enumeration_list right_bracket
| left_bracket
^ character_enumeration_list right_bracket
| left_bracket : regular_charset_id : right_bracket
character_enumeration ::= character_specifier
| character_specifier – character_specifier
regular_charset_id ::= ALPHA | UPPER | LOWER
| DIGIT | ALNUM
Поскольку в синтаксических правилах регулярных выражений символы « Создаваемое по приведенным правилам регулярное выражение представляет собой символьную строку, содержащую все символы, которые требуется явно сопоставлять с символами строки-источника. В строке могут находиться специальные символы, представляющие собой заменители обычных символов (« Рассмотрим несколько примеров регулярных выражений. Выражение Выражение Специальный символ « Другая форма определения набора символов иллюстрируется регулярным выражением Определяемый набор символов может задаваться нижней и верхней границей диапазона значений кодов допустимых символов. Например, в регулярном выражении Наконец, имеется еще одна возможность определения набора символов. Соответствующая конструкция позволяет указать, какие символы из общего набора символов SQL не входят в определяемый набор символов. Например, регулярное выражение Как и в предикате В заключение данного пункта вернемся к отложенному в разделе 17.2 «Скалярные выражения» лекции 17 обсуждению функции
SUBSTRING (character_value_expression
SIMILAR character_value_expression
ESCAPE character_value_expression)
Предположим, что в разделе Вот пример вызова функции: SUBSTRING ( 'This is string22'
SIMILAR 'This is\"[:ALPHA:]+\"[:DIGIT:]+'
ESCAPE '\' )
Результатом будет строка Примеры запросов с использованием предиката similarПример 18.14. Найти номера и названия отделов, название которых начинается со слов SELECT DEPT_NAME, DEPT_NO
FROM DEPT
WHERE DEPT_NAME SIMILAR TO
'(HARD|SOFT)WARE%\_[:DIGIT:]+' ESCAPE '\';
Пример 18.15. Найти номера и названия проектов, название которых не начинается с последовательности цифр. SELECT DEPT_NAME, DEPT_NO FROM DEPT WHERE DEPT_NAME SIMILAR TO '[^1-9]+%'; 18.2.7. Предикат existsПредикат exists_predicate ::= EXISTS (query_expression) Значением условия Примеры запросов с использованием предиката existsПример 18.16. Найти номера отделов, среди служащих которых имеются менеджеры проектов. SELECT DEPT.DEPT_NO
FROM DEPT
WHERE EXISTS
(SELECT EMP.EMP_NO
FROM EMP
WHERE EMP.DEPT_NO = DEPT.DEPT_NO
AND EXISTS
(SELECT PRO.PRO_MNG
FROM PRO
WHERE PRO.PRO_MNG = EMP.EMP_NO));
Эту формулировку можно упростить, избавившись от самого вложенного запроса (пример 18.16.1): SELECT DEPT.DEPT_NO
FROM DEPT
WHERE EXISTS
(SELECT EMP.EMP_NO
FROM EMP, PRO
WHERE EMP.DEPT_NO = DEPT.DEPT_NO
AND PRO.PRO_MNG = EMP.EMP_NO);
Далее заметим, что по смыслу SELECT DEPT.DEPT_NO
FROM DEPT
WHERE EXISTS
(SELECT *
FROM EMP, DEPT
WHERE EMP.DEPT_NO = DEPT.DEPT_NO
AND PRO.PRO_MNG = EMP.EMP_NO);
Запросы с предикатом SELECT DEPT.DEPT_NO
FROM DEPT
WHERE (SELECT COUNT(*)
FROM EMP, DEPT
WHERE EMP.DEPT_NO = DEPT.DEPT_NO
AND PRO.PRO_MNG = EMP.EMP_NO ) >= 1;
Пример 18.17. Найти номера отделов, размер заработной платы служащих которых не превышает размер заработной платы руководителя отдела. SELECT DEPT.DEPT_NO
FROM DEPT
WHERE NOT EXISTS
(SELECT *
FROM EMP EMP1, EMP EMP2
WHERE EMP1.EMP_NO = DEPT.DEPT_MNG AND
EMP2.DEPT_NO = DEPT.DEPT_NO AND
EMP2.EMP_SAL > EMP1.EMP_SAL);
18.2.8. Предикат uniqueЭтот предикат позволяет сформулировать условие отсутствия дубликатов в результате запроса: unique_predicate ::= UNIQUE (query_expression) Результатом вычисления условия Примеры запросов с использованием предиката uniqueПример 18.18. Найти номера отделов, служащих которых можно различить по имени и дате рождения. SELECT DEPT_NO
FROM DEPT
WHERE UNIQUE
(SELECT EMP_NAME, EMP_BDATE
FROM EMP
WHERE EMP.DEPT_NO = DEPT.DEPT_NO);
Возможна альтернативная, но более сложная формулировка этого запроса с использованием предиката SELECT DEPT_NO
FROM DEPT
WHERE NOT ESISTS
(SELECT *
FROM EMP, EMP EMP1
WHERE EMP1.EMP_NO <> EMP.EMP_NO
AND EMP.DEPT_NO = DEPT.DEPT_NO
AND EMP1.DEPT_NO = DEPT.DEPT_NO
AND EMP1.EMP_NAME = EMP.EMP_NAME
AND(EMP1.EMP_BDATE = EMP.EMP_BDATE
OR (EMP.EMP_BDATE IS NULL
AND EMP1.EMP_BDATE IS NULL)));
Если же ограничиться требованием уникальности имен служащих, то возможна следующая формулировка (пример 18.18.2): SELECT DEPT_NO
FROM DEPT
WHERE (SELECT COUNT (EMP_NAME)
FROM EMP
WHERE EMP.DEPT_NO = DEPT.DEPT_NO) =
(SELECT COUNT (DISTINCT EMP_NAME)
FROM EMP
WHERE EMP.DEPT_NO = DEPT.DEPT_NO);
18.2.9. Предикат overlapsЭтот предикат служит для проверки перекрытия во времени двух событий. Условие определяется следующим синтаксисом:
overlaps_predicate ::= row_value_constructor OVERLAPS
row_value_constructor
Степень каждой из строк-операндов должна быть равна 2. Тип данных первого столбца каждого из операндов должен быть типом даты-времени, и типы данных первых столбцов должны быть совместимы. Тип данных второго столбца каждого из операндов должен быть типом даты-времени или интервала. При этом:
Пусть (S1 > S2 AND NOT (S1 >= T2 AND T1 >= T2)) OR (S2 > S1 AND NOT (S2 >= T1 AND T2 >= T1)) OR (S1 = S2 AND (T1 <> T2 OR T1 = T2)) Примеры запросов с использованием предиката overlapsПример 18.19. Найти номера проектов, которые выполнялись в период с 15 января 2000 г. по 31 декабря 2002 г. SELECT PRO_NO
FROM PRO
WHERE (PRO_SDATE, PRO_DURAT) OVERLAPS
(DATE '2000-01-15', DATE '2002-12-31');
Пример 18.20. Найти названия проектов, которые будут выполняться в течение следующего года. SELECT PRO_TITLE FROM PRO WHERE (PRO_SDATE, PRO_DURAT) OVERLAPS (CURRENT_DATE, INTERVAL '1' YEAR); 139 В стандарте SQL:1999 разрешается применять предикат
|
|
CITForum © 1997–2025