[(имя—столбца[ , имя—столбца] . . .)]
Как обычно, подзапрос не может включать ни оператора UNION, ни фразы ORDER BY. Однако при этих ограничениях любая таблица, выборка которой может быть осуществлена с помощью предложения SELECT, может быть, с другой стороны, определена как представление. Ниже приведено несколько примеров.
1. CREATE VIEW КРАСНЫЕ_ДЕТАЛИ (НОМЕР—ДЕТАЛИ,
Действие этого оператора заключается в том, чтобы создать новое представление, названное xyz.КРАСНЫЕ_ДЕТАЛИ, где xyz — известное системе имя пользователя, издавшего предложение CREATE VIEW. Пользователь xyz может называть это представление просто КРАСНЫЕ_ДЕТАЛИ. Другие же пользователи должны называть его xyz.КРАСНЫЕ_ДЕТАЛИ. С другой стороны, они могут, конечно, ввести для него синоним, как указывалось в главе 7. В этом представлении четыре столбца — НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ВЕС и ГОРОД, соответствующих четырем столбцам НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ВЕС и ГОРОД лежащей в основе базовой таблицы Р. Если имена столбцов явно не специфицированы в предложении CREATE VIEW, то представление очевидным образом наследует имена столбцов его источника. В приведенном примере наследуемыми именами были бы НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ВЕС и ГОРОД. Имена столбцов должны быть специфицированы явно для всех столбцов представления, если: а) какой-либо столбец этого представления продуцируется с помощью стандартной функции, арифметического выражения или константы (и не имеет, следовательно, имени, которое он мог бы наследовать) или б) два или более столбцов имели бы в противном случае одно и то же имя. Каждый из этих двух случаев иллюстрируется в следующих двух примерах.
2. CREATE VIEW PQ (НОМЕР_ДЕТАЛИ, ОБЩЕЕ_КОЛИЧЕСТВО)
Внутренняя структура системы DB2 является весьма сложной, как и следует ожидать от системы, соответствующей современному уровню развития и обеспечивающей все функции, которыми обычно обладают современные СУБД (в том числе, например, управление восстановлением, параллельными процессами, санкционированием доступа и т. д.), и многое сверх того. Однако многие из этих функций не представляют непосредственного интереса для пользователя (в нашем понимании этого термина, т. е. конечного пользователя или прикладного программиста), хотя они и имеют решающее значение для общего функционирования системы. С точки зрения пользователя, систему можно фактически рассматривать как состоящую просто из четырех основных компонентов, которые называются следующим образом[6]:
Программа управления хранимыми данными (STORED DATA MANAGER).
Функции этих четырех компонентов в общих чертах заключаются и следующем.
Прекомпилятор является препроцессором для языков прикладного программирования (ПЛ/1, КОБОЛ, ФОРТРАН и язык ассемблера). Его функция состоит в том, чтобы проанализировать исходный модуль на любом из этих языков, удалить из него все найденные предложения SQL, заменяя их предложениями CALL входного языка. На стадии исполнения эти предложения CALL будут передавать управление непосредственно супервизору времени исполнения. Из предложений SQL, которые ему встречаются, Прекомпилятор строит модуль запросов к. базе данных (DHRM), который используется в качестве входных данных для генератора планов прикладных задач, рассматриваемого ниже.
один или более DBRM и создать тем самым план прикладной задачи. План прикладной задачи содержит необходимые команды машинного кода, реализующие первоначальные предложения SQL, из которых были построены эти DBRM. Он включает, в частности, команды обращения к программе управления хранимыми данными (см. ниже).
Рассмотрим сначала пример программы Р на языке ПЛ/1 (точнее, исходный модуль Р на языке ПЛ/1), которая включает плюс или более предложений SQL. Язык ПЛ/1 здесь взят для определенности. Суммарный процесс остается, по существу, неизменным и для других языков. Прежде чем программа Р может быть скомпилирована компилятором ПЛ/1, она должна быть обработана прекомпилятором (рис. 2.2). Примечание. Если Р содержит также какие-либо предложения CICS (вида ЕХЕС, СICS...;), то она должна быть также обработана препроцессором СICS. Прекомпилятор DB2 и препроцессор CICS могут исполнятся при этом в любом порядке.
Рис. 2.2. Прекомпиляция
Как указывалось в предыдущем разделе, прекомпилятор DB2 удаляет все найденные им в Р предложения SQL и заменяет[7]
их предложениями CALL языка ПЛ/1. (Эти предложения CALL осуществляют обращения к интерфейсному модулю ПЛ/1—см. ниже.) Предложения SQL он использует при этом для построения модуля запросов к базе данных
(DBRM) программы Р, который хранится вне этой программы как раздел библиотечного набора данных. В DBRM содержится копия первоначальных предложений SQL вместе с внутренней формой этих предложений в виде дерева разбора. Прекомпилятор формирует также листинг исходной программы, содержащий первоначальный исходный текст программы, диагностические сообщения, таблицы перекрестных ссылок и т. д.
Далее, модифицированный исходный модуль на языке ПЛ/1 компилируется и редактируется обычным образом за исключением того, что интерфейсный модуль языка ПЛ/1, который предоставляется системой DB2, должен быть частью входной информации для редактора связей. Условимся называть результат этого шага «загрузочным модулем Р на языке ПЛ/1».
Теперь мы подошли к шагу генератора планов прикладных задач (рис. 2.3).
В действительности, этот компонент является оптимизирующим компилятором. Он преобразует запросы высокого уровня к базе данных (на самом деле, предложения SQL) в оптимизированную машинную программу. Входной информацией для генератора служит множество, состоящее из одного или более DBRM. Таких модулей запросов будет несколько, если первоначальная программа на ПЛ/1 состоит более чем из одной внешней процедуры, т. е. включает несколько исходных модулей. Результат работы генератора, т. е. скомпилированный им код, называется планом прикладной задачи и он хранится в системной базе данных, называемой каталогом[8]
Выдать фамилии поставщиков, которые поставляют по крайней мере одну красную деталь.
Пояснение.
Результатом самого внутреннего подзапроса является множество ('Р1, 'Р4', 'Р6'). Подзапрос следующего уровня в свою очередь дает в результате множество ('S1', 'S2', 'S4'). Последний, самый внешний SELECT, вычисляет приведенный выше окончательный результат. Вообще допускается любая глубина вложенности подзапросов.
Для того чтобы убедиться в Вашем понимании этого примера, попытайтесь выполнить следующие упражнения:
а) Перепишите данный запрос так, чтобы все уточнения имен были указаны явным образом.
б) Напишите эквивалентную формулировку этого же запроса с использованием соединения.
Выдать номера поставщиков, находящихся в том же городе, что и поставщик S1.
|
НОМЕР_ПОСТАВЩИКА
|
S1
S4
Иногда пользователь может знать, что заданный подзапрос должен возвратить в точности одно значение, как в рассматриваемом примере. В таком случае можно использовать вместо обычного IN более простой оператор сравнения (например, =, > и т. д.). Однако, если подзапрос возвращает более одного значения и не используется оператор IN, будет возникать ошибка. Ошибка не возникнет, если подзапрос не возвратит вообще ни одного значения. При этом сравнение интерпретируется в точности так, как если бы подзапрос возвратил неопределенное значение. Иными словами, если х — переменная, то сравнение
х простой—оператор—сравнения (подзапрос),
где «подзапрос» возвращает пустое множество, имеет значение истинности не истина или ложь, а неизвестно
(см. главу 4, пример 4.2.10).
Нужно отметить, что сравнение в предыдущем примере должно быть записано именно так, как показано — подзапрос должен следовать за оператором сравнения. Иначе говоря, следующая запись запроса некорректна:
SELECT НОМЕР_ПОСТАВЩИКА
FROM S
WHERE (SELECT ГОРОД
FROM S
WHERE НОМЕР_ПОСТАВЩИКА = 'S1') = ГОРОД;
Более того, подзапрос не может включать фраз GROUP BY или HAVING, если он используется с простым оператором сравнения, например с =, > и т. д.
ПОДЗАПРОСЫ
В этом разделе обсуждаются подзапросы или вложенные предложения SELECT. Говоря нестрого, подзапрос представляет собой выражение SELECT-FROM-WHERE, которое вложено в другое такое предложение [13]'. Обычно подзапросы используются для представления множества значений, исследование которых должно осуществляться в каком-либо предикате IN, как иллюстрируется в следующем примере.
Предмет обсуждения этой книги, система
Предмет обсуждения этой книги, система DB2, представляет собой программный продукт фирмы IBM, функционирующий в обстановке операционной системы MVS, а точнее — реляционную систему управления базами данных для MVS. Это означает, что рассматриваемый программный продукт позволяет пользователю (как конечному пользователю, так и прикладному программисту) в такой операционной обстановке запоминать данные в базах данных и осуществлять их выборку, воспринимая при этом базу данных как совокупность отношений или таблиц. DB2 обеспечивает доступ к таким базам данных посредством реляционного языка, называемого SQL («Structured Query Language» — Структуризованный язык запросов).
Вряд ли можно сказать, что название «DB2» вносит какую-либо ясность — оно мало что говорит о природе этого программного продукта. Ненамного лучше и полное его название — «IBM Database 2» («База данных 2 фирмы IBM»). В частности, из него, не ясно, что речь идет о реляционном программном продукте, или что он поддерживает язык SQL, или, наконец, что он функционирует в обстановке MVS. Более того, такое название даже и не совсем корректно, поскольку это вовсе не база данных, а система управления базами данных. Столь неблагоприятное начало не может, однако, затушевать того факта, что DB2 является исключительно важным продуктом. Его объявление в июне 1983 г. было значительным событием: оно окончательно наложило печать одобрения IBM на то, что стало называться реляционным подходом к. управлению базами данных. Этот подход, впервые предложенный в 1969—70-х годах Э. Ф. Коддом из Научно-исследовательской лаборатории фирмы IBM в Сан-Хосе, с тех пор медленно, но уверенно получал признание в самой фирме IBM и вне ее. DB2 занимает в настоящее время ведущее место среди основных программных продуктов IBM. Все они—реляционные, поддерживают язык SQL и функционируют в обстановке одной из главных операционных систем IBM: DB2 — в обстановке MVS, SQL/DS — DOS/VSE и SQL/DS Release 2 — VM/CMS.
Как только что упоминалось, реляционный подход был впервые предложен в 1969—70-х годах. Язык SQL был разработан в 1974 году, а основная реализация — прототип этого языка под названием System R — была создана и исследована IBM в течение приблизительно пятилетнего периода — в 1975—79 годах. Разработанная в рамках этого прототипа технология была далее использована в SQL/DS", первое полностью поддерживаемом реляционном программном продукте IBM, объявленном для DOS/ VSE в 1981 году, а для VM/CMS — в 1983 году. Впоследствии. она была использована и в DB2, объявленной для MVS в 1983 году. Все эти продукты — System R, SQL/DS и DB2 — внешне очень похожи. В частности, во всех трех системах очень похож язык SQL. Поэтому, несмотря на то что данная книга посвящена системе DB2, большинство сказанного в ней относится с небольшими изменениями также к System R и SQL/DS. Однако, начиная с этого места и далее, ссылка на «язык SQL», если не оговаривается иное, должна относиться специально к диалекту этого языка, поддерживаемому DB2.
Основная задача этой книги— дать подробное описание продукта DB2, не лишенное, однако, некоторых критических замечаний: что он собой представляет и чего не представляет, для чего он предназначен и как он может быть использован. Книга ориентирована на специалистов по управлению обработкой данных, по организации работы конечных пользователей, на специалистов в области баз данных, в том числе администраторов баз данных, системных администраторов, проектировщиков баз данных и прикладных программистов, работающих в обстановке баз данных. Она рассчитана также на студентов, специализирующихся в области обработки данных, на преподавателей этих дисциплин, на конечных пользователей и профессиональных специалистов по обработке данных, желающих расширить свои знания в области баз данных путем изучения системы, воплощающей современный уровень развития технологии баз данных. На протяжении всей книги при этом основное внимание уделяется пользователю, где под «пользователем» мы понимаем, главным образом, конечного пользователя либо прикладного программиста. Дается достаточно основательная интерпретация материала, ориентированного на пользователя, например материала, связанного с языком SQL. Наоборот, подробности, представляющие интерес только для системных программистов или операторов, связанные, например, с системными командами, вообще опущены или, в лучшем случае, обсуждаются только в общих чертах. Предполагается, что читатели имеют по крайней мере некоторое представление об общей структуре, концепциях и назначении систем баз данных. Однако от них не требуется, по существу, каких-либо знаний в области реляционных систем.
Книга имеет следующую структуру. В главах 1 и 2 приводится обзор возможностей системы DB2, показывающий, каким образом она соотносится с ее обстановкой и, в общих чертах, как она функционирует. Глава 3 посвящена определению данных, а главы 4—6 — манипулированию данными. В главе 7 обсуждается системный каталог. В главе 8 описываются специальные реляционные возможности, называемые механизмом представлений. В главе 9 обсуждается подсистема безопасности данных DB2, в частности показывается, как представления, о которых идет речь в предыдущей главе, могут использоваться для обеспечения безопасности. Главы 10—12 имеют дело с прикладным программированием. Наряду с другими вопросами в них обсуждается использование языка SQL для написания прикладных программ, довольно подробно освещаются вопросы обработки транзакций, в том числе соображения, касающиеся восстановления целостности данных и параллелизма. В главе 13 рассматриваются структуры хранения данных системы DB2. В главе 14 описывается интерактивный интерфейс DB2I, а в главе 15—периферийный программный продукт QMF (Query Management Facility), позволяющий запрашивать данные из базы данных и генерировать отчеты. Наконец, в главе 16 подытоживаются достоинства системы типа DB2, обсуждаются некоторые соображения о производительности, высказываются предположения о будущем реляционных систем. В книге содержится значительное число проверенных на ЭВМ примеров и в большинстве глав — множество упражнений вместе с ответами к ним.
Предлагаемая монография принадлежит перу известного
Предлагаемая монография принадлежит перу известного специалиста в области баз данных, одного из пионеров технологии реляционных баз данных— К. Дейта.
Эта работа посвящена детальному обсуждению нового программного продукта, созданного крупнейшим в мире производителем средств вычислительной техники и программного обеспечения—американской фирмой International Business Machines Corporation (IBM), в которой автор сотрудничал в течение многих лет. Речь идет о реляционной СУБД DB2, поставляемой фирмой с 1983 года. Появление на рынке программного обеспечения такого крупного программного продукта — весьма значительное событие. В немалой степени это связано и с тем, что он относится к такой сложной и перспективной области, как реляционные базы данных.
Прежде чем предоставить читателю возможность начать знакомство с системой, целесообразно кратко охарактеризовать предысторию ее создания. Это поможет лучше осознать проблемы, связанные с разработкой систем такого класса, объективно оценить научно-технический уровень системы DB2, понять, почему именно фирма IBM смогла создать такой сложный программный продукт.
Подход, основанный на реляционной модели данных, занял важное место в развитии технологии баз данных. Нет необходимости подробно обсуждать здесь его достоинства, как, впрочем, и трудности, связанные с его реализацией и использованием — они достаточно хорошо известны. Системами реляционного типа оснащены сегодня многие серийно выпускаемые модели ЭВМ, от мощных вычислительных комплексов до персональных компьютеров. Реляционный инструментарий предполагается использовать в качестве основного средства управления базами данных и базами знаний в разрабатываемых проектах ЭВМ нового поколения.
Значительный вклад в разработку теории реляционных баз данных и создание СУБД этого класса внесла фирма IBM. Еще в конце 60-х годов в ряде ее научных центров начали активно проводить теоретические исследования и экспериментальные разработки новых нетрадиционных подходов к управлению данными, базирующихся на строгом математическом понятии отношения. Необходимо было при этом решить целый ряд задач — определить целесообразную архитектуру СУБД нового типа, разработать новую модель данных, адекватные ей методы доступа и технологию обработки запросов, создать языковые средства, ориентированные на теоретико-множественный характер структур данных и операций над ними, предложить пути реализации программных систем такого типа, обеспечивающие достаточно высокую их производительность, создать прототипы будущих коммерческих СУБД, обладающих указанными возможностями, и экспериментально оценить их характеристики на ЭВМ.
Разработки, связанные с системами нового типа, получившими название «реляционных», проводились и многими другими группами специалистов. Однако именно результаты, полученные в этой области сотрудниками IBM, оказали определяющее влияние на формирование новой ветви в технологии баз данных.
В этой связи следует назвать прежде всего новаторские работы Э. Кодда, посвященные реляционной модели данных и ее математическим основам: исследования в области реляционной алгебры и реляционного исчисления, разработка алгоритма редукции (интерпретации выражений реляционного исчисления в реляционной алгебре), создание одного из первых реляционных языков, формулировка концепции реляционной полноты языка, разработка основ теории нормализации отношений. До сих пор повсеместно цитируется известная статья Кодда, опубликованная еще в 1970 году в журнале Communications of the ACM. Не здесь ли был впервые введен термин «реляционная модель данных»? Позднее, в 1979 году, Кодд опубликовал фундаментальную работу, в которой систематизируются и обобщаются результаты исследований ряда авторов, направленных на повышение семантического уровня моделей данных. В работе Кодда предлагается ввести в базовую реляционную модель новые механизмы, обеспечивающие более развитые возможности для формулировки ограничений целостности, или, иначе говоря, для выражения семантики предметной области. Тем самым были преодолены значительные трудности, связанные с использованием реляционной модели данных. Расширенная таким образом модель была названа автором RM/T.
Исследования Кодда в области реляционных баз данных получили широкое признание. В 1981 г. он был удостоен весьма престижной Тьюринговской премии, присуждаемой Ассоциацией по вычислительной технике США (ACM) за выдающийся вклад в развитие информатики.
Заслуживает внимания другой весьма интересный комплекс исследований, выполненный М. Сенко и руководимой им группой. Был предложен и конструктивно, вплоть до языковых спецификаций, проработан оригинальный подход к построению СУБД, в котором используется частный случай реляционной модели данных—модель бинарных отношений. Основная цель этого подхода, получившего название Data Independent Access Method (DIAM),—развитие концепций многоуровневой архитектуры СУБД, обеспечивающих высокую степень независимости данных. В публикациях группы Сенко, а впоследствии в большой серии принадлежащих ему лично статей и Докладов детально специфицированы все уровни архитектуры СУБД, реализующей предлагаемый подход. В частности, рассмотрены специальные методы доступа, организация среды хранения и способы представления хранимых данных, сформулированы ключевые идеи модели бинарных отношений и предложен синтаксис пользовательского языка FORAL (для версии DIAM II). Идеи СУБД с многоуровневой архитектурой были высказаны в этих работах за несколько лет до публикации известного отчета ANSI/SPARC (1975 г.), на который обычно ссылаются по этому поводу. В рамках DIAM специально изучались также возможности использования дисплея со световым пером для оперирования графическим представлением схемы базы данных. Эту работу можно рассматривать как одну из ранних попыток создания инструментария автоматизированного проектирования баз данных. К сожалению, подход DIAM не был практически реализован в какой-либо коммерческой системе. Весьма вероятно, что причиной этому явилась скоропостижная кончина М. Сенко.
Особое внимание в исследованиях IBM уделялось разработке языковых средств реляционных систем баз данных. Важное место при этом отводилось изучению психологических аспектов применения таких языков, с тем чтобы минимизировать потенциальную возможность пользовательских ошибок.
Наиболее заметными в этом направлении являются работы Д. Чемберлина, Р. Бойса и их соавторов по созданию реляционного языка, упоминаемого в литературе как SEQUEL или SQL (в процессе эволюции языка было создано несколько его версий). Благодаря большой популярности и тщательности отработки SEQUEL приобрел статус стандарта де-факто. Его описание можно найти в каждой более или менее серьезной монографии или учебном пособии по реляционным базам данных. И не случайно Комитет по разработке стандартов в области баз данных Американского национального института стандартов принял SEQUEL в качестве отправной точки в своей деятельности по созданию стандарта реляционного языка.
Наряду с SEQUEL следует указать здесь и другое направление работ IBM в области реляционных языков, связанное с именем М. Злуфа. Цель заключалась в создании более «дружественного» по сравнению с SEQUEL реляционного интерфейса, которым можно было бы воспользоваться, не обладая специальной профессиональной подготовкой в области баз данных. Исследования Злуфа увенчались созданием получившего широкую известность языка Query-By-Example (QBE). В отличие от SEQUEL, близкого по стилю к языкам программирования, QBE является «графически-ориентированным» языком и предназначен специально для интерактивной работы. Пользователь оперирует на экране дисплея формами таблиц, составляющих базу данных, и продуцируемых из них таблиц. Для спецификации запроса задаются образцы заполнения строк этих таблиц, ограничения, которым удовлетворяют их элементы, и требуемые операции над строками таблиц. В более сложных случаях применяются также другие средства языка. Интерфейс QBE поддерживается в ряде программных продуктов. Об одном из них идет речь в этой книге.
Нужно сказать, наконец, о разработках, направленных на создание собственно программного инструментария для реляционных баз данных, в основу которых были положены рассмотренные теоретические исследования. Понимая все трудности, связанные с созданием эффективной реляционной СУБД на существующем оборудовании, фирма не спешила с созданием коммерческого продукта, предназначенного для массового применения. Чтобы не дискредитировать идею с самого начала, нужна была известная осторожность.
Первым «пробным шаром» фирмы в этой области, вызвавшим большой интерес, явилась экспериментальная реляционная СУБД System R, в которой реализован язык SEQUEL. Работы над системой проводились в 1975—1979 гг. и дали возможность определить рациональные пути реализации систем подобного типа.
Развитие System R осуществлялось в двух направлениях. Одно из них — создание системы управления распределенными базами данных. Результатом этих работ стала система R*, которой посвящены многочисленные публикации. Другое направление — создание на основе System R коммерческой реляционной СУБД. Эта задача была решена к 1981 г., когда фирма начала поставку своего первого коммерческого реляционного продукта — системы SQL/DS. Спустя два года был сделан еще один шаг в этом направлении — IBM начала поставлять новую систему DB2, которой и посвящена предлагаемая монография К. Дейта.
Можно без преувеличения сказать, что система DB2 интегрирует весь арсенал современных достижений в технологии реляционных баз данных. Как видно из сказанного, ее разработке предшествовала многолетняя подготовительная работа — проведение разносторонних научных исследований, создание экспериментальных реализации и прототипов будущих программных продуктов, изучение их характеристик.
При создании системы DB2 особое внимание уделялось проблеме повышения ее производительности. В частности, DB2 реализована с этой целью по принципу компиляции запросов, тогда как в большинстве других существующих систем осуществляется их интерпретация. Связанное с этим решением определенное отступление в отношении независимости данных компенсируется в некоторой степени за счет принятия специальных мер. Тщательно продумана организация среды хранения данных, предусмотрен ряд механизмов, служащих для оптимизации обработки запросов, на самом современном уровне решены вопросы управления параллельным исполнением транзакций.
В качестве пользовательского языка в системе реализована новая версия все того же SEQUEL (называемого здесь SQL). На его основе строится как интерфейс включающего языка для прикладных программ («встроенный SQL»), так и интерактивный интерфейс для пользователя. Особый интерес представляет «динамический SQL»—интерфейс, позволяющий обрабатывать системными средствами запросы (SQL-тексты), задаваемые в прикладной программе как значения переменных типа литерной строки. Это позволяет легко создавать на основе DB2 различные интерактивные прикладные системы, причем отображение пользовательского языка в SQL осуществляется прикладной программой с помощью «динамического SQL».
Для системы DB2 предусмотрены различные варианты операционной обстановки, и пользователь может выбрать для себя наиболее подходящий. Совместно с системой могут использоваться такие полезные программные продукты, как QMF и DXT. QMF — это генератор отчетов, функционирующий по отношению к DB2 как периферийный компонент. Он позволяет специфицировать запросы не только на языке SQL, но и на QBE. В свою очередь, DXT дает возможность обрабатывать с помощью DB2 данные, хранимые в базах данных системы IMS или в наборах данных VSAM.
Совместимость системы DB2 и DXT имеет важное значение для расширения сферы ее потенциального применения. Благодаря этому новой системе открываются двери в те области, которые уже «обжиты» другой СУБД, созданной фирмой IBM,— системой IMS. За два десятилетия, прошедшие с момента начала ее поставки, система IMS получила массовое распространение — сфера ее действия стала весьма широкой. Поэтому забота о совместимости DB2 и DXT не лишена оснований.
На этом можно завершить обзор разработок фирмы IBM в области реляционных баз данных, поскольку читатель уже получил достаточно полное представление о предыстории создания системы DB2, и пора сказать несколько слов о самой книге.
Она представляет собой профессионально написанное руководство по системе DB2. В ней содержатся необходимые сведения об операционной обстановке системы, ее организации и архитектуре, принципах функционирования, порядке взаимодействия с программными продуктами QMF и DXT. Центральное место отводится детальному обсуждению функций языка SQL и особенностей его использования для всех предусмотренных пользовательских интерфейсов. В заключительной главе сжато характеризуются общие возможности системы DB2, рассматривается проблема производительности реляционных систем вообще и применительно к DB2, намечаются перспективы развития функциональных возможностей этой системы.
Читателю будет полезен и материал приложений. Здесь приведены строгие определения основных понятий реляционной модели данных, излагается точка зрения на вопрос о том, какая система имеет право называться «реляционной», рассматриваются важные методологические аспекты логического проектирования баз данных. Приводятся также требования системы DB2 и сопутствующих ей программных продуктов к операционной обстановке и оборудованию ЭВМ. Для справочных целей включена сводка синтаксических спецификаций предложений манипулирования данными языка SQL.
Новая работа К. Дейта не только будет интересна специалистам по программному обеспечению информационных систем, но и с успехом может быть использована как учебное пособие по реляционным СУБД. Для этого в книге при всей ее лаконичности имеется все необходимое — от концепций реляционной модели данных и методологии проектирования реляционных баз данных до систематического рассмотрения архитектуры, пользовательских интерфейсов и технологии функционирования самой современной СУБД такого класса, от теоретического материала до технических спецификаций и проверенных на ЭВМ многочисленных практических упражнений и ответов к ним. Книга хорошо скомпонована, написана четким и ясным языком. Умело подобран иллюстративный материал.
В заключение коротко об авторе. С начала 70-х годов К. Дейт занимается реляционными базами данных и стал одним из ведущих специалистов в этой области. В течение многих лет он тесно сотрудничал с Э. Коддом, которому в знак признательности он посвящает эту книгу. К. Дейт — один из руководителей и непосредственный участник разработки системы DB2. Знание системы «изнутри» помогло объективно показать не только ее достоинства, но и слабые места.
Можно не сомневаться в том, что советский читатель получил полезную и нужную книгу.
М. Когаловский
ПРЕДЛОЖЕНИЕ DELETE
Предложение DELETE имеет следующий общий формат:
DELETE
FROM таблица
[WHERE предикат];
Удаляются все записи в «таблице», которые удовлетворяют «предикату».
Удалить все поставки тех поставщиков, которые находятся в городе, заданном переменной включающего языка ГОРОД.
ЕХЕС SQL DELETE
FROM SP
WHERE :ГОРОД=
(SELECT ГОРОД
FROM S
WHERE S.HOMEP_ПОСТАВЩИКА =
SP.НОМЕР_ПОСТАВЩИКА);
И снова, если никакие записи не удовлетворяют условию WHERE, для поля SQLCODE будет установлено значение +100.
ПРЕДЛОЖЕНИЕ INSERT
Предложение INSERT имеет следующий общий формат:
INSERT
INTO таблица [(поле [,поле] . . .)]
VALUES (константа [,константа] . . .);
ИЛИ:
INSERT
INTO таблица [(поле [,поле] . . .)]
подзапрос;
В первом формате в «таблицу» вставляется строка, имеющая заданные значения для указанных полей, причем 1-я константа в списке констант соответствует i-му полю в списке полей. Во втором формате вычисляется «подзапрос»; копия результата, представляющего собой, вообще говоря, множество строк, вставляется в «таблицу». При этом 1-й столбец этого результата соответствует f-му полю в списке полей. В обоих случаях отсутствие списка полей эквивалентно спецификации списка всех полей в таблице (см. ниже пример 6.4.2).
Вставить в таблицу Р новую деталь. При этом номер детали, название и вес заданы соответственно переменными включающего языка НОМ_ДЕТАЛИ, НАЗВ_ДЕТАЛИ и ВЕС_ДЕТАЛИ, а цвет и город неизвестны.
ЕХЕС SQL INSERT
INTO Р (НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ВЕС)
VALUES (:HOM_ДЕТАЛИ, :НАЗВ_ДЕТАЛИ,
:ВЕС_ДЕТАЛИ);
Опять здесь можно использовать индикаторные переменные. Например, если ЦВЕТ_ДЕТАЛИ и ГОР_ДЕТАЛИ — две следующие переменные включающего языка, ИНД_ЦВЕТА и ИНД_ГОРОДА — соответствующие индикаторные переменные, то последовательность
ИНД_ЦВЕТА = -1;
ИНД_ГОРОДА = -1;
ЕХЕС SQL INSERT
INTO Р (НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ЦВЕТ, ВЕС,
ГОРОД)
VALUES (:HOM_ДЕТАЛИ, :НАЗВ_ДЕТАЛИ,
:ЦВЕТ_ДЕТАЛИ: ИНД_ЦВЕТА,
:ВЕС_ДЕТАЛИ,
:ГОР_ДЕТАЛИ: ИНД_ГОРОДА);
дает тот же результат, что и приведенное выше предложение INSERT.
Для простоты в дальнейшем (в этой и двух следующих главах) будем в большинстве случаев игнорировать индикаторные переменные и возможность неопределенных значений.
ПРЕДЛОЖЕНИЕ UPDATE
Предложение UPDATE имеет следующий общий формат:
UPDATE таблица
SET поле = выражение
[,поле = выражение] . . .
[WHERE предикат];
Все записи в «таблице», которые удовлетворяют «предикату», обновляются в соответствии с присваиваниями «поле = выражение» во фразе SET (установить).
Увеличить состояние всех поставщиков из Лондона на величину, заданную переменной включающего языка ПРИРОСТ:
ЕХЕС SQL UPDATE S
SET СОСТОЯНИЕ = СОСТОЯНИЕ + :ПРИРОСТ
WHERE ГОРОД = 'Лондон';
Если записей, удовлетворяющих условию WHERE, нет, для поля SQLCODE будет установлено значение +100. Справа от знака присваивания во фразе SET может быть использована индикаторная переменная. Например, предложение:
ИНД_РАНГА = -1;
ЕХЕС SQL UPDATE S
SET СОСТОЯНИЕ = :РАНГ :ИНД_РАНГА
WHERE ГОРОД = 'Лондон';
установит состояние всех лондонских поставщиков в неопределенное значение. То же самое можно, конечно, сделать с помощью предложения:
ЕХЕС SQL UPDATE S
SET СОСТОЯНИЕ = NULL
WHERE ГОРОД = 'Лондон';
ПРЕДЛОЖЕНИЯ COMMIT И ROLLBACK
Из предыдущего раздела должно быть ясно, что COMMIT и ROLLBACK в действительности не являются такими же операциями управления базой данных, как SELECT, UPDATE и т. д. Предложения COMMIT и ROLLBACK—это вообще не команды для СУБД. Они представляют собой команды для администратора транзакций, который не является, конечно, частью СУБД. Наоборот, СУБД подчиняется администратору транзакций в том смысле, что СУБД — это только один из нескольких возможных «администраторов ресурсов», которые обеспечивают обслуживание транзакций, выполняемых под управлением этого администратора транзакций. В частности, в случае системы DB2 имеются три таких администратора транзакций — IMS, CICS и TSO, и заданная транзакция DB2 может исполняться под управлением в точности одного из них. Как уже указывалось (в несколько иных терминах) в главе 1:
— транзакция, исполняемая под управлением администратора транзакций IMS, может использовать услуги трех администраторов ресурсов — системы баз данных IMS, системы передачи данных IMS и системы DB2;
— транзакция, исполняемая под управлением администратора транзакций CICS, также может использовать услуги трех администраторов ресурсов — опять-таки системы баз данных IMS, системы передачи данных CICS и системы DB2;
— транзакция, исполняемая под управлением администратора транзакций TSO, может использовать услуги двух администраторов ресурсов — терминальной системы TSO и системы DB2.
Рассмотрим транзакцию, которая обновляет как базу данных системы IMS, так и базу данных системы DB2. Если эта транзакция завершается успешно, то все произведенные ею обновления как данных IMS, так и данных DB2, должны быть зафиксированы. Наоборот, если она завершается неудачно, то для всех
произведенных ею обновлений должен быть осуществлен откат. Не должна допускаться такая возможность, чтобы обновления для IMS были зафиксированы, а для обновлений в DB2 был осуществлен откат, и наоборот. При этом транзакция не была бы больше атомарной (все или ничего). Очевидно, таким образом, что для транзакции не имеет смысла издавать, например, COMMIT для IMS и ROLLBACK для DB2. И если даже в обоих случаях издаются одинаковые команды, в системе может все же возникнуть отказ в промежутке между ними, и результат будет неудовлетворительным. Следовательно, транзакция должна издавать единственную общесистемную команду COMMIT (или ROLLBACK), адресуя се соответствующему администратору транзакций, а этот администратор транзакций в свою очередь гарантирует, что все администраторы ресурсов в унисон будут фиксировать или осуществлять откат обновлений, за которые они ответственны. (Более того, он обеспечивает такую гарантию, даже если возникнет отказ системы в ходе этого процесса, благодаря протоколу, называемому двухфазной фиксацией. Однако подробности об этом протоколе выходят за рамки этой книги (Заинтересованный читатель может найти подробное обсуждение этого вопроса в книге Д. Ульмана «Основы систем баз данных» (М.: Финансы и статистика, 1983).— Примеч. пер.)
Именно поэтому СУБД подчиняется (подчиняются) администратору транзакций. COMMIT и ROLLBACK должны быть глобальными (общесистемными) операциями, и администратор транзакций действует как необходимый центральный пункт управления, который обеспечивает, чтобы это было так.
Из предыдущего также ясно, почему требуются различные функции «фиксации» и «отката» при трех разных вариантах операционной обстановки системы DB2. Поскольку они вообще являются не операциями DB2, а, скорее, операциями администратора транзакций, они должны запрашиваться в том стиле, который предписан для рассматриваемого администратора транзакций. В обстановке TSO они запрашиваются с помощью явных операторов языка SQL — COMMIT и ROLLBACK (подробности приведены ниже). В случае IMS и CICS они запрашиваются с помощью соответствующих обращений к IMS и CICS, подробности о которых можно найти в руководствах фирмы IBM по этим системам. В остальной части данного раздела основное внимание уделено обстановке TSO[20].
Прежде чем перейти к подробному рассмотрению предложений COMMIT и ROLLBACK как таковых, определим сначала важное понятие «точка синхронизации». Точка синхронизации представляет собой граничную точку между двумя последовательными транзакциями. Грубо говоря, она соответствует концу логической единицы работы и таким образом является точкой, в которой база данных находится в непротиворечивом состоянии. Точка синхронизации учреждается при инициации программы, издании COMMIT и ROLLBACK и только в этих случаях. Напомним, однако, что COMMIT и ROLLBACK иногда могут быть неявными.
Предложение COMMIT
Предложение COMMIT языка SQL имеет следующий формат:
COMMIT [WORK];
Это предложение сигнализирует об успешном завершении транзакции и учреждает точку синхронизации. Все обновления, сделанные данной программой со времени предыдущей точки синхронизации, фиксируются. Все открытые курсоры закрываются. Снимаются все блокировки записей. Блокировки, установленные с помощью LOCK TABLE, вероятно, не будут сняты (см. разделы 11.5 и 11.6).
Необязательный операнд
WORK (работа) является чисто вспомогательным и не оказывает какого- либо влияния на выполнение этого предложения.
Предложение ROLLBACK
Предложение ROLLBACK языка SQL имеет следующий формат:
ROLLBACK [WORK];
Это предложение сигнализирует о неудачном завершении транзакции и учреждает точку синхронизации. Все обновления, сделанные программой после учреждения последней точки синхронизации, аннулируются. Все открытые курсоры закрываются. Снимаются все блокировки записей. Однако блокировки, установленные с помощью LOCK TABLE, вероятно, не будут сняты (см. разделы 11.5 и 11.6).
Необязательный операнд
WORK является чисто вспомогательным и не оказывает какого-либо влияния на выполнение этого предложения.
Предыдущие определения порождают ряд вопросов, явно заслуживающих более серьезного обсуждения.
1. Прежде всего отметим, что каждая операция в системе DB2 исполняется в контексте некоторой транзакции. Это касается и операций SQL, которые вводятся в интерактивном режиме через интерфейс DB2I. Точки синхронизации для операций, введенных через интерфейс DB2I, учреждаются способом, который рассматривается в главе 14.
2. Из приведенных определений следует, что транзакции не могут быть вложены одна в другую, поскольку каждое из предложений COMMIT или ROLLBACK завершает одну транзакцию и инициирует другую.
3. Следствием предыдущего пункта является тот факт, что исполнение отдельной программы состоит из последовательности одной или более транзакций (часто, но совсем не обязательно, только одной). Если это только одна транзакция, часто будет возможно кодировать программу вообще без каких-либо явных предложений COMMIT или ROLLBACK.
Наконец, из всего сказанного выше следует, что транзакции являются не только единицами работы, но также и единицами восстановления. Если транзакция успешно выполнит операцию COMMIT, то администратор транзакций должен гарантировать, что сделанные ею обновления будут обязательно отражены в базе данных, даже если в следующий момент будет иметь место отказ системы. Вполне возможно, например, что отказ системы произойдет после того, как будет выполнена операция COMMIT, но прежде, чем обновления будут физически записаны в базу данных,—они могли еще оставаться в буфере в основной памяти, и поэтому утратились бы во время такого отказа системы. Даже если это случится, процедура рестарта системы все же установит эти обновления в базе данных. Она способна восстановить значения, которые должны быть записаны в базу данных благодаря анализу соответствующих записей в журнале. (Из этого следует, в частности, что запись в журнал будет физически осуществляться до того, как может завершиться обработка операции COMMIT. Это правило называется протоколом упреждающей записи в журнал.)
Таким образом, процедура рестарта будет восстанавливать любые единицы работы (транзакции), которые завершились успешно, но для которых не удалось физически записать сделанные ими обновления до того, как произойдет отказ. Следовательно, как утверждалось выше, транзакция с достаточным на то основанием может определяться и как единица восстановления.
ПРЕДЛОЖЕНИЯ GRANT И REVOKE
Рассмотренный в разделе 9.3 механизм представлений концептуально позволяет различными способами подразделить базу данных на подмножества таким образом, чтобы секретные сведения могли быть скрыты от пользователя, не обладающего правом доступа. Однако в нем не предусматривается спецификация тех операций, которые разрешается выполнять над этими подмножествами полномочному пользователю. Эту функцию выполняют предложения GRANT (предоставить) и REVOKE (отменить) языка SQL, которые обсуждаются ниже.
Прежде всего, чтобы вообще быть способным выполнить какую-либо операцию в DB2, пользователь должен обладать соответствующей привилегией (или полномочиями) на выполнение этой операции. В противном случае операция будет отвергнута с выдачей надлежащего сообщения об ошибке или кода исключительного состояния. Например, чтобы успешно выполнить предложение
SELECT *
FROM S;
пользователь должен обладать привилегией на выполнение операции
SELECT над таблицей S. В системе DB2 предусматривается широкий диапазон привилегий. Вообще говоря, каждая привилегия попадает, однако, в один из следующих классов:
а) привилегии на таблицы., связанные с такими операциями, как SELECT, которые выполняются над таблицами — как над базовыми таблицами, так и над представлениями;
б) привилегии на планы, которые имеют отношение к таким вещам, как полномочия на выполнение заданного плана прикладной задачи;
в) привилегии на базу данных, которые касаются таких операций, как создание таблицы в конкретной базе данных;
г) привилегии на использование, которые связаны с использованием определенных объектов среды хранения, а именно: с группами хранения, табличными пространствами и буферными пулами (см. главу 13);
и, наконец,
д) системные
привилегии, имеющие отношение к некоторым общесистемным операциям, таким, как операция создания новой базы данных.
Имеются также некоторые «пакетированные» привилегии, которые фактически служат кратким обозначением для совокупностей других привилегий, не всегда относящихся в точности к одному из указанных выше пяти классов. В частности, привилегия системного администрирования SYSADM является кратким обозначением для совокупности всех других привилегий в системе. Таким образом, пользователь, обладающий привилегией SYSADM, может выполнять любую операцию во всей системе при условии ее корректности. Примером операции, которая не была бы «корректной» в этом смысле, могла бы быть попытка уничтожить одну из таблиц каталога. Этого не может делать даже пользователь, обладающий привилегией SYSADM.
Итак, когда система DB2 впервые устанавливается, некоторая часть процесса установки требует назначения одного особо привилегированного пользователя системным администратором этой установленной системы. Для DB2 системный администратор идентифицируется идентификатором санкционирования доступа, точно так же, конечно, как и все другие пользователи. Этот пользователь, который автоматически получает привилегию SYSADM, становится ответственным за общее управление системой в течение всей продолжительности ее жизни. Например, в обязанности системного администратора входит текущий контроль за функционированием системы, сбор статистики о ее производительности и учетной информации. Но мы обсуждаем здесь лишь вопросы безопасности. Поэтому вернемся к главной теме обсуждения. Сначала имеется, таким образом, один пользователь, который может делать все, в частности, он или она может предоставлять привилегии другим пользователям, и никто иной не может делать вообще все.
Отметим, между прочим, что, хотя системный администратор является, конечно, обладателем привилегии SYSADM, не все обладатели привилегии SYSADM являются системными администраторами. Привилегия SYSADM может быть в дальнейшем предоставлена также другим пользователям, но эта привилегия может быть впоследствии снова отменена. Для системного администратора привилегия SYSADM никогда не может быть отменена[18].
Далее, пользователь, который создает некоторый объект, например базовую таблицу, автоматически получает полные привилегии на этот объект, включая, в частности, привилегию предоставления таких привилегий другому пользователю. Конечно, «полные привилегии» не включают здесь привилегий, которые не имеют смысла. Если, например, пользователь U обладает только привилегией на выполнение операции SELECT над базовой таблицей Т и создает некоторое представление V, которое основано на Т, то U, естественно, не получает привилегии на выполнение операции UPDATE над V. Подобным же образом, если U создает представление С, которое является соединением таблиц А и В, то U не получает привилегии на выполнение операции UPDATE над С, независимо от того, обладал ли он такими привилегиями для таблиц А и В, поскольку система DB2 не допускает каких-либо операций обновления по отношению к представлению, являющемуся соединением.
Предложение GRANT
Предоставление привилегий осуществляется с помощью предложения GRANT (предоставить). Общий формат этого предложения:
GRANT привилегии [ON тип — объектов объекты] ТО пользователи;
где «привилегии» — список, состоящий из одной или более привилегий, разделенных запятыми, либо фраза ALL PRIVILEGES (все привилегии); «пользователи» — это список, включающий один или более идентификаторов санкционирования, разделенных запятыми, либо специальное ключевое слово PUBLIC (общедоступный); «объекты» — это список имен одного или более объектов одного и того же типа, разделенных запятыми; наконец, «тип — объектов» указывает тип этого объекта или этих объектов. Фраза ON не используется, если предоставляемые привилегии являются системными.
Приведем несколько примеров.
Привилегии на таблицы
GRANT SELECT ON TABLE S TO ЧАРЛИ;
GRANT SELECT, UPDATE (СОСТОЯНИЕ, ГОРОД) ON TABLE S
TO ДЖУДИ, ДЖЕК, ДЖОН;
GRANT ALL PRIVILEGES ON TABLE S, P, SP TO УОЛТ, ТЕД;
GRANT SELECT ON TABLE P TO PUBLIC;
GRANT DELETE ON S TO ФИЛ;
Примечание. Если «тип—объектов»—TABLE (таблица), его можно опустить, как показано в последнем примере.
Привилегии на планы:
GRANT EXECUTE ON PLAN ПЛАН1 TO ДЖУДИ;
Привилегии на базу данных:
GRANT CREATETAB ON DATABASE DBX TO ШАРОН;
Пользователю Шарону разрешается создавать таблицы в базе данных DBX. Организация баз данных в системе DB2 обсуждается в главе 13.
Привилегии на использование:
GRANT USE ON TABLESPACE TSE TO КОЛИН;
Пользователю Колину разрешается использовать табличное пространство TSE для хранения любых таблиц, которые он может создавать. Более подробную информацию по этому вопросу также можно найти в главе 13.
Системные привилегии:
GRANT CREATEDBC ТО ЖАК, МАРИАН;
Пользователям Жаку и Мариан разрешается создавать новые базы данных. Если они будут это делать, то автоматически получат привилегию DBCTRL на эти базы данных (см. в конце данного раздела).
Здесь не ставилась задача в полной мере и исчерпывающим образом рассмотреть все множество привилегий, которые признает система DB2. Однако будут полностью рассмотрены привилегии на таблицы, поскольку они, вероятно, представляют наиболее широкий интерес. К таблицам (как к базовым таблицам, так и к представлениям) относятся следующие привилегии:
SELECT
UPDATE (может относиться к конкретным столбцам)
DELETE
INSERT
Две остальные привилегии относятся только к базовым таблицам:
ALTER (привилегия на исполнение предложения ALTER TABLE над данной
таблицей)
INDEX (привилегия на исполнение предложения CREATE INDEX над данной
таблицей)
Для того чтобы создать
таблицу, требуется, как уже говорилось, привилегия CREATETAB для базы данных, к которой относится эта таблица. Для создания представления требуется привилегия SELECT на каждую таблицу, упоминаемую в определении этого представления. Заметим, что привилегия SELECT, в отличие от UPDATE, не может относиться к конкретным столбцам. Причина заключается в том, что эффекта привилегии SELECT, распространяющейся на конкретные столбцы, всегда можно добиться путем предоставления привилегии SELECT, не относящейся к конкретным столбцам, на представление, состоящее как раз из рассматриваемых столбцов.
Предложение REVOKE
Если пользователь U1 предоставляет какую-либо привилегию некоторому другому пользователю U2, то пользователь U1 может впоследствии отменить эту привилегию для пользователя U2. Отмена привилегий осуществляется с помощью предложения REVOKE (отменить), общий формат которого очень похож на формат предложения GRANT:
REVOKE привилегии [ON тип — объектов объекты] FROM пользователи;
Отмена данной привилегии для данного пользователя приводит к тому, что все планы прикладных задач, связывание которых осуществлялось этим пользователем, помечаются как «недействительные» и, следовательно, автоматически приводит при следующем вызове каждого такого плана к повторному связыванию. Этот процесс, по существу, аналогичен тому, что происходит, когда уничтожается такой объект, как индекс. Ниже приводится несколько примеров предложения REVOKE:
REVOKE SELECT ON TABLE S FROM ЧАРЛИ;
REVOKE UPDATE ON TABLE S FROM ДЖОН;
REVOKE CREATETAB ON DATABASE DBX FROM НАНСИ, ДЖЕК;
REVOKE SYSADM FROM СЭМ;
Отмена привилегии
UPDATE не может относиться к конкретным столбцам.
Факультативная возможность GRANT
Если пользователь U1 имеет полномочия на предоставление привилегии Р другому пользователю U2, то пользователь U1 имеет также полномочия на предоставление привилегии Р пользователю U2 «с возможностью GRANT» (путем спецификации фразы WITH GRANT OPTION в предложении GRANT). Передача таким образом возможности GRANT от пользователя U1 пользователю U2 означает, что U2 теперь в свою очередь имеет полномочия на предоставление привилегии Р некоторому третьему пользователю U3. И, следовательно, U2, конечно, также обладает полномочиями на передачу возможности GRANT с таким же успехом пользователю U3 и т. д. Например:
Пользователь U1:
GRANT SELECT ON TABLE S TO U2 WITH GRANT OPTION;
Пользователь U2:
GRANT SELECT ON TABLE S TO U3 WITH GRANT OPTION;
Пользователь U3:
GRANT SELECT ON TABLE S TO U4 WITH GRANT OPTION;
и т. д. Если пользователь U1 издает теперь предложение:
REVOKE SELECT ON TABLE S FROM U2;
то отмена будет распространяться каскадом, т. е. будут автоматически отменены также передачи привилегий пользователем U2 пользователю U3 и пользователем U3 пользователю U4. Заметим, однако, что из этого не следует, что пользователи U2, U3 и U4 более не имеют привилегии SELECT на таблицу S—они могут помимо этого иметь такие привилегии, полученные от некоторого другого пользователя U5. Когда пользователь U1 издает предложение REVOKE, то фактически аннулируются только привилегии, которые предоставлялись этим пользователем. Рассмотрим, например, следующую последовательность событий.
Пользователь U1 в момент времени t1:
GRANT SELECT ON TABLE S TO U2 WITH GRANT OPTION;
Пользователь U5 в момент времени t2:
GRANT SELECT ON TABLE S TO U2 WITH GRANT OPTION;
Пользователь U2 в момент времени t3:
GRANT SELECT ON TABLE S TO U3;
Пользователь U1 в момент времени t4:
REVOKE SELECT ON TABLE S FROM U2;
Пусть при этом t1<t2<t3<t4.
Предложение REVOKE, изданное пользователем U1 в момент времени t4, фактически не лишает пользователя U2 привилегии на таблицу S, поскольку пользователь U2 получил эту привилегию также от U5 в момент времени t2. Поскольку далее предложение GRANT пользователя U2 для пользователя U3 было выполнено в момент времени t3 и t3> t2, то, возможно, что это GRANT было привилегией, которая была получена от пользователя U5, а не от U1. Поэтому пользователь U3 также не утрачивает этой привилегии. И если бы в момент t4 предложение REVOKE издал бы пользователь U5, а не U1, пользователи U2 и U3 также все еще сохранили бы эту привилегию. U2 сохранил бы привилегию, полученную от U1, и GRANT, изданный пользователем U2, мог бы, вероятно, служить для предоставления привилегии, полученной от U1, а не от U5, и пользователь U3 снова не утратил бы привилегию. Предположим, однако, что имела место другая последовательность событий.
Пользователь U1 в момент времени t1:
GRANT SELECT ON TABLE S TO U2 WITH GRANT OPTION;
Пользователь U2 в момент времени t2:
GRANT SELECT ON TABLE S TO U3 WITH GRANT OPTION;
Пользователь U5 в момент времени t 3:
GRANT SELECT ON TABLE S TO U2 WITH GRANT OPTION;
Пользователь U1 в момент времени t4:
REVOKE SELECT ON TABLE S FROM U2;
Тогда REVOKE пользователя U1 в момент времени t4 не будет лишать пользователя U3 привилегии SELECT на таблицу S, поскольку пользователь U2 получил эту привилегию также от U5 в момент t3. Однако, в противоположность предыдущему примеру, U3, утратит привилегию в этот момент времени, поскольку GRANT пользователя U2, возможно, имел дело с привилегией, полученной от пользователя U1.
Возможность GRANT нельзя отменить, не отменяя в то же время привилегии, к которой эта возможность относится.
Пакетированные (административные) привилегии
Для справочных целей завершим этот раздел кратким обзором пяти «пакетированных» привилегий, а именно: SYSADM, DBADM, DBCTRL, DBMAINT, SYSOPR.
— SYSADM
Привилегия SYSADM («системный администратор») позволяет ее обладателю выполнять любую операцию, которую поддерживает система.
— DBADM
Привилегия DBADM («администрирование базой данных»)
— относительно конкретной базы данных позволяет ее обладателю выполнять любую операцию, которую поддерживает система для этой базы данных.
— DBCTRL
Привилегия DBCTRL («управление базой данных») относительно конкретной базы данных позволяет ее обладателю выполнять любую операцию, которую поддерживает система для этой базы данных, за исключением операций доступа к значениям данных в этой базе данных, т. е. такие обслуживающие операции, как «восстановить базу данных», допускаются, а операции манипулирования данными языка SQL—нет.
— DBMAINT
Привилегия DBMAINT («ведение базы данных») относительно конкретной базы данных позволяет ее обладателю выполнять над этой базой данных обслуживающие операции, связанные только с чтением данных, например вспомогательную операцию «копировать содержимое базы данных в среде хранения».
— SYSOPR
Привилегия SYSOPR («системный оператор») позволяет ее обладателю выполнять системные функции оператора консоли, например операции начала и завершения трассировки функционирования системы.
Для конкретной базы данных привилегии категории DBADM включают DBCTRL, а привилегии DBCTRL включают DBMAINT. И конечно же, SYSADM включает привилегии всех других категорий.
ПРЕДМЕТНЫЙ УКАЗАТЕЛЬ
B
B-дерево, 193
А
Автоматическая навигация, 33
Администратор базы данных, 136, 186
— системный, 136
— транзакций, 163
Алгебра реляционная, 234
Анализ на непротиворечивость, 169
Аргумент (динамический SQL), 182
Ассоциация, 241
Атомарность значений данных, 24
— операций, 164
— транзакций, 163
Атрибут, 26
Б
База данных, 186
— —по умолчанию, 195
— —
пользовательская, 186
— — реляционная, 22
— — системная, 186
Безопасность данных, 132
— представления, 133
Блок условия, 211
Блокирование, 169
Блокировка монопольная, 169
— совместная, 170
В
Вариант CHECK, 118
— GRANT, 138
Восстановление, 166
Г
Генератор деклараций DCLGEN, 155
— планов прикладных задач, 35
Генерация кода, 38
Граф ожидания, 179
Группа памяти, 188
— — по умолчанию, 196
— повторяющаяся, 25
Д
Данные скрытые, 128
Домен, 231
Е
Единица блокирования, 176
— восстановления, 166
Ж
Журнал, 163
З
Зависимость от незафиксированного обновления, 167
— функциональная, 249
Запись хранимая, 190
Значение неопределенное, 45
— — в арифметическом выражении, 55
— — в индексе с параметром UNIQUE, 47
— — в предложении SELECT DISTINCT, 60
— — в предложении UPDATE, 98
— — в сравнениях, 59
— — во встроенном языке, 149
— — во фразе GROUP BY, 86
— — во фразе ORDER BY, 60
— — при проектировании базы данных, 252
И
Идентификатор записи, 191
— санкционирования доступа, 132
Импликация, 81
Имя, 43
— представления, 116
— уточненное, 53
Индекс, 138, 187, 188, 190
— кластеризации, 190
Интерфейс интерактивный, 197
Исключение дубликатов, 54
К
Каталог, 39, 109
Квантор, 77
— общности FORALL, 79
— существования, 77
Классификация связей, 241
— сущностей, 240
Кластеризация внутритабличная, 190
— межтабличная, 190
Ключ альтернативный, 233
— внешний, 234
— возможный, 233
Команда BIND, 201
— DISPLAY FORM, 204
— DISPLAY REPORT, 205
— DRAW COND, 212
— FREE, 201
— PRINT REPORT, 205
— REBIND, 201
— RUN QUERY, 204
— DRAW, 210
Константы, 45
Кортеж, 231
Курсор, 151
—, стабильноcть его, 175
М
Макетирование, 223
Манипулирование данными, 28
Модель данных реляционная, 25
Модуль запросов к базе данных, 34
— языка программирования интерфейсный, 37
Н
Навигация, 31
— автоматическая, 221
— ручная, 221
Независимость данных, 40, 222
— логическая, 222
— физическая, 40
Нормализация, 240, 248
О
Области рабочая QUERY, 204
— дескрипторов SQLDA, 183
— рабочая FORM, 205
— рабочая временная, 204
— связи SQLCA, 183
Обновление данных, 98
— —
незафиксированное, 167
— —утраченное, 167
Обозначение, 241
Обстановка операционная системы DB2, 20
Ограничение санкционирования доступа, 132
Оператор сравнения ALL, 71
— — ANY, 71
Операция декартова произведения, 236
— деления, 237
— присваивания реляционная, 238
— проекции, 236
— разности, 236
— соединения, 237
Отношение, 232
— базовое, 234
Отношения, совместимые по объединению, 235
Отчет, 204
П
Параметр UNIQUE, 47
— динамического SQL, 182, 184
Переменная включающего языка, 146
— индикаторная, 149
— системная USER, 134
План прикладной задачи, 35, 38
Подзапрос, 72
— коррелированный, 74
Подтип сущностей, 251
Поле SQLCODE, 147
Пользователь, 28
Предикат BETWEEN, 57
— IN, 57
— — с подзапросами, 72
— LIKE, 58
Предлжение DELETE CURRENT, 153
— INSERT встроенного языка, 150
— ALTER TABLE, 46
— CLOSE, 151
— COMMENT ON, 112
— COMMIT, 155
— CREATE INDEX, 47
— CREATE SYNONYM, 113
— CREATE TABLE, 43, 46
— CREATE VIEW, 115
— DECLARE CURSOR, 151
— DECLARE TABLE, 146
— DELETE, 99
— DELETE встроенного языка, 150
— DROP INDEX, 48
— DROP SYNONYM, 113
— DROP TABLE, 46
— DROP VIEW, 118
— EXECUTE, 182
— FETCH, 151
— GRANT, 135
—INCLUDE (декларация), 155
— INCLUDE SQLCA, 147
— INCLUDE SQLDA, 183
— INSERT, 100
— LOCK TABLE, 174
— OPEN курсор, 152
— PREPARE, 181
— REVOKE, 135
— ROLLBACK, 156
— SELECT, 53
— SELECT вложенное, 72
— SELECT встроенного языка, 148
— SELECT единичное, 148
— SELECT обработка, 90
— SELECT*, 55
— UPDATE, 98
— UPDATE CURRENT, 153
— UPDATE встроенного языка, 149
— WHENEVER, 155
Представление, условие обновляемости, 121
Представления, 29
Преимущества реляционных систем, 220
Прекомпилятор, 34
Привилегия, 135
— BCTRL, 140
— DBADM, 140
— DBMAINT, 140
— SYSADM, 140
— SYSOPR, 140
— административная, 140
— требуемая пользователю, 140
Приложение интерактивное, 21
— пакетное, 21
Принцип двухрежимный, 145
Проверка полномочий, 38
—правильности плана, 201
Программа управления хранимыми данными, 36
Проектирование базы данных, 240
Производительность системы, 225
Пространство индексное, 186
— табличное, 186
— — по умолчанию, 189
— — простое, 189
— — табличное сегментированное, 190
Протокол упреждающей записи в журнал, 166
Процедура проверки достоверности, 192
— редактирования, 191
Процессор SPUFI, 199
Псевдоним, 66
ПсевдоЯОД, 245
Пул буферный, 196
Путь доступа, 38
Р
Реорганизация, 189
Реструктуризация, 126
С
Свойство, 240
Связь, 240
Сегментирование пространства, 189
Синоним, 113
Система R*, 230
— SQL/DS, 230
— реляционная, 238
Ситуация тупиковая, 176
Словарь данных (каталог), 109
Спецификация DISTINCT, 53
Средство программное DL/1 Extract, 22
— — DXT, 22
— — QMF, 22
Степень отношения, 233
Страница, 186
Супервизор стадии исполнения, 35
Сущность, 240
— ассоциативная, 240
— стержневая, 240
—
характеристическая, 240
Т
Таблица, 42
— базовая, 42
— виртуальная, 30
— каталога, 109
— хранимая, 186
Тип данных, 44
Точка синхронизации, 165
Транзакция, 162
У
Умолчание системное, 188
Управление параллельными процессами, 166
Уровень изоляции, 175
Утилита, 202
Ф
Фиксация автоматическая, 163
— двухфазная, 165
Форма отношения нормальная, 248
— отчета по умолчанию, 204
Фраза FOR UPDATE, 152
— GROUP BY, 85
— HAVING, 86
— NOT NULL, 45
— ORDER BY (определение курсора), 152
— ORDER BY (предложение SELECT), 56
— USING (предложения EXECUTE), 182
— USING (предложение FETCH), 184
Функция стандартная AVG, 83
— — COUNT (*), 83
— — MIN, 83
— — SUM, 83
— — МАХ, 83
Х
Характеристика, 241
Ц
Целостность по ссылкам, 99, 234
— — сущностям, 234
Ч
Число кардинальное отношения, 233
Чтение повторяемое, 175
Э
Эквисоединение, 62
Элемент образца, 212
Я
Язык QBE, 210
— SQL встроенный, 145
— SQL динамический, 180
— SQL интерактивный, 197
— SQL статический, 185
[1]
В этой книге мы будем использовать термин «MVS» для обозначения как стандартной операционной системы MVS (т. е. системного продукта фирмы IBM «Multiple Virtual Systems»), так и расширенной ее версии, называемой MVS/XA («MVS/Extended Architecture»). Каждая ссылка в этом тексте на MVS относится в равной степени к обеим ее версиям.
[2]
В интересах точности следует заметить, что TSO в действительности не является «подсистемой» в том специальном смысле, в котором этот термин используется в MVS Скорее она является неотъемлемой частью самой MVS. Можно приобрести систему MVS без IMS или CICS, но нельзя без TSO. Но эти различия не представляются важными для наших целей, и для простоты мы будем рассматривать в этой книге все три компонента как подсистемы.
[3]
Для читателей, хорошо знающих MVS и/или TSO, заметим, что пакетное приложение TSO есть не что иное, как обычное пакетное приложение MVS, которое исполняется под управлением телемонитора TSO (ТМР). См. раздел 14.9.
[4]
Формат хранимых данных — это, конечно, не единственное, чем отличаются эти две системы. Имеется ряд других отличий, о которых упоминается ниже. Большинство из них связано с тем фактом, что система DB2 специально разработана для обстановки больших систем (MVS). Например, объем данных в базе данных, которые могут запоминаться в интерактивном режиме в системе DB2, ограничивается только объемом памяти, доступной в таком режиме, в то время как система SQL/DS ограничивается единственной базой данных, функционирующей в интерактивном режиме, объемом 64 гигабайта (теоретический максимум; практический максимум несколько меньше). Подобным образом механизм безопасности данных системы DB2 значительно более тщательно разработан, чем в SQL/DS, отражая тог факт, что существует, вероятно, намного больше пользователей и намного больше категорий пользователей для установки DB2, чем для SQL/DS. Детальный разбор всех таких различий не является целью этой книги.
[5]
В этой книге предложения SQL, команды и т. п. для ясности записываются прописными буквами. На практике же обычно более удобно вводить такие предложения и команды строчными буквами. Система DB2 допускает то и другое.
[6]
В фирменных руководствах по системе термины «RUNTIME SUPERVISOR» или «STORED DATA MANAGER» не используются.
[7] Он оставляет также копию каждого такого предложения
SQL в модифицированом исходном модуле в форме комментария.
[8]
Точнее, план хранится в справочнике
DB2, который в действительности является расширением каталога, предназначенным только для использования самой системой. С точки зрения пользователя разница между ними состоит в том, что каталог в отличие от справочника имеет форму, позволяющую делать к нему запросы с помощью обычных предложений SQL (см. главу 7).
[9]
Кроме того, в качестве имен не могут использоваться ключевые слова языка SQL (CREATE, TABLE, SELECT и т. д.). Первая литера любого имени должна быть буквой (А—Z или одной из специальных литер ^, $, @), а остальные литеры — буквами, цифрами (0-9) или знаком подчеркивания. Имена таблиц и столбцов могут содержать максимум 18 литер, а имена пользователей—максимум 8 литер.
[10]
Если n>254, то поле является и «длинным полем», и объектом строгих ограничений. Длинные поля предназначены для того, чтобы иметь дело с данными в свободном формате, такими, как длинные текстовые строки, а не с простыми форматизированными данными, например номер поставщика или объем поставки. По существу, единственной операцией, в которой могут в качестве операндов использоваться такие поля, является операция присваивания базе данных (INSERT или UPDATE) либо из базы данных (SELECT). He допускаются какие-либо операции, которые предполагают сравнение с длинным полем Поэтому, например, длинные поля не могут быть индексированными, на них нельзя ссылаться во фразах WHERE, GROUP BY или ORDER BY и т. п. Две последние фразы рассматриваются в главах 4 и 5.
[11]
В связи с этим фактом можно сказать, что реляционные таблицы образуют замкнутую систему относительно операторов выборки данных языка, подобного SQL. Вообще говоря, замкнутая система—это совокупность (возможно, бесконечная) объектов некоторого типа, например OBJS, и соответствующая совокупность операторов, например OPS, таких, что а) операторы из OPS применяются ни к объектам из OBJS и б) результат применения любого такого оператора к любому такому объекту (любым таким объектам) является другим объектом из OBJS. Практический смысл этого соображения (в частности, для случая отношений) заключается в следующем. Поскольку результатом одной операции SELECT является другое отношение, то, по крайней мере, принципиально возможно применить другую операцию SELECT к этому результату, конечно, предусматривая, чтобы он был где-либо сохранен. Это означает, также, опять-таки принципиально, что операции SELECT могут быть вложенными друг в друга. Такая возможность иллюстрируется в разделах 5.2, 6.4 и 8.1.
[12]
Все они имеют значение истинности «неизвестно».
При наличии неопределенных значений необходимо принять трехзначную логику, значениями истинности в которой являются: истина, ложь и неизвестно.
«Неизвестно» в действительности представляет собой, по сути дела, неопределенное значение истинности. Предложение SELECT осуществляет выборку записей, для которых предикат WHERE имеет значение истина, т. е. не ложь и не неизвестно.
[13] Подзапрос может включать также фразы GROUP BY и HAVING. Однако комбинация ORDER BY и UNION недопустима.
[14] Между прочим, этот пример иллюстрирует важный момент, заключающийся в том, что порядок кванторов существен в выражениях, содержащих кванторы обоих типов Выражение FORALLx(EXISTSy (y>x)) истинно. Однако выражение EXISTSy(FORALLx(yx))—«существует действительное у такое, что для всех действительных х справедливо у больше х», т.е. «существует некоторое число, большее всех других чисел», — которое получается из предыдущего выражения просто перестановкой порядка кванторов, является ложным.
[15] EXISTS (существует) также рассматривается как стандартная функция, но она отличается от функций, обсуждаемых в данном разделе, тем, что она возвращает значение истинности, а не арифметическое или строковое значение, т. е это не числовая функция.
[16] Этого результата («группы внутри групп» и т. д.) можно достигнуть, однако, с помощью QMF. См. главу 15.
[17]
Каталог не является одинаковым в различных реализациях языка SQL, поскольку он по необходимости содержит для конкретной системы много информации, специфичной для этой системы. В частности, каталоги DB2 и SQL/DS различны.
[18]
Не следует, конечно, понимать этот абзац таким образом, что имеется фактически единственное лицо, которое на все время является системным администратором, даже если это лицо, например, покидает компанию. Имеется, скорее, один неизменный идентификатор санкционирования, который рассматривается системой как идентифицирующий системного администратора. Каждый, кто может войти в систему с этим идентификатором (и может выдержать тесты на достоверность), будет считаться системным администратором, пока он или она не выйдет из системы. Эти тесты на достоверность могут и, конечно, должны время от времени изменяться.
[19]
На самом деле, внутренняя структура этих наборов данных VSAM значительно отличается во всяком случае от структуры, которая предполагается для VSAM, поскольку управление всем их пространством осуществляется DB2, а не средствами VSAM (см главу 13). Таким образом, попытка понять их содержимое была бы нетривиальной задачей, даже если бы их можно было обработать с помощью обычных обращений к VSAM.
[20] Мы ограничимся при этом лишь обстановкой прикладного программировании. Предложения COMMIT и ROLLBACK могут быть введены и в интерактивном режиме, но делать это на практике не рекомендуется, как будет ясно позднее в этой главе, поскольку это обычно означает, что блокировки будут установлены на нежелательно долгое время.
[21]
При определенных условиях, которые здесь детально не обсуждаются, эта блокировка будет сниматься в следующей точке синхронизации, а не при завершении программы. В частности, это будет происходить в случае, если предложение LOCK TABLE вводится через DB2I (что само по себе маловероятно).
[22] Сегментированное пространство может иметь несколько групп памяти для каждого сегмента (см. раздел 13.3).
[23] Интересно отметить, что пространство памяти в 64 гигабайта со страни-1|яМ11 по 4К эквивалентно приблизительно 128 токам, т. е. 32 устройствам пря-Мпго доступа IBM 3380.
[24] Установка системы всегда располагает факультативной возможностью вообще не использовать какую-либо группу памяти для заданного пространства или его сегмента. Если это так, то для определения, расширения и удаления наборов данных необходимым образом следует использовать утилиту обслуживания методов доступа VSAM. Подробное обсуждение этих вопросов выходит за рамки данной книги.
[25]
Нельзя отрицать, что сегодня большинство систем, даже систем реляционного типа, тем не менее действительно проявляет весьма зависимое от ситуации и непредсказуемое поведение в некоторых областях. Для примера можно сослаться на обработку обновления представления в системе DB2, при которой действительно обнаруживается в некоторой степени неприятный произвол (см. раздел 8.4). Но такой произвол имеет тенденцию проявиться именно в тех вопросах, где реализация отклонилась от базовой теории. Так, важнейшим компонентом реляционной модели данных является понятие первичного ключа (см. Приложение А). Однако в системе DB2 такие ключи не поддерживаются, и это упущение является непосредственной причиной упоминаемого выше произвола. Конечно, система DB2—не единственный «правонарушитель» в этом отношении; подобная критика относится к большинству других систем, известных в момент написания этой книги, однако DB2 может служить для иллюстрации нежелательных последствий пренебрежения предписаниями модели, положенной в ее основу.
[26]
Дополнительным доказательством такого признания может служить тот факт, что Ассоциация по вычислительной технике (The Association for computing Machinery—ACM) присудила Тьюринговскую премию за 1981 год доктору Кодду, первому архитектору реляционной модели, за его работы, посвященные этой модели. Тьюринговская премия присуждается ежегодно за важнейшие работы в области информатики. По всеобщему признанию, она является наиболее престижной наградой во всей информатике.
[27]
Такая операция, как ALTER TABLE, в языке .SQL может рассматриваться не как изменение степени отношения с n на n+l, а, скорее, как создание нового отношения степени n+1 из отношения степени п.
[28]
' Под «соединением» здесь понимается либо естественное соединение, либо эквисоединение.
[29]
Это предложение включает также комментарий и ключевое слово FIELDS. Ни то ни другое не является частью реального ЯОД системы DB2.
ПРЕДСТАВЛЕНИЯ И БЕЗОПАСНОСТЬ
Чтобы проиллюстрировать использование представлений для целей безопасности, приведем ряд примеров, основанных (по большей части) опять-таки на базе данных поставщиков и деталей.
1. Пользователю разрешен доступ к полным записям поставщиков, но лишь для поставщиков, находящихся в Париже:
CREATE VIEW ПАРИЖСКИЕ_ПОСТАВЩИКИ
AS SELECT НОМЕР_ПОСТАВЩИКА, ФАМИЛИЯ,
СОСТОЯНИЕ, ГОРОД
FROM S
WHERE ГОРОД = 'Париж';
Пользователи этого представления видят «горизонтальное подмножество» (или, точнее, подмножество строк, подмножество, зависящее от значений) базовой таблицы S.
2. Пользователю разрешен доступ ко всем записям поставщиков, но не к рейтингам поставщиков (значение поля СОСТОЯНИЕ):
CREATE VIEW СКРЫТОЕ_СОСТОЯНИЕ
AS SELECT НОМЕР_ПОСТАВЩИКА, ФАМИЛИЯ,
ГОРОД
FROM S;
Пользователи этого представления видят «вертикальное подмножество» (или, точнее, подмножество столбцов, независимое от значений) подмножество базовой таблицы S.
3. Пользователю разрешен доступ к записям поставщиков только для поставщиков, находящихся в Париже, но не к рейтингам поставщиков:
CREATE VIEW ПАРИЖСКИЕ_БЕЗ_РЕЙТИНГОВ
AS SELECT НОМЕР_ПОСТАВЩИКА, ФАМИЛИЯ, ГОРОД
FROM S
WHERE ГОРОД = 'Париж';
Пользователи этого представления видят подмножество строк и столбцов базовой таблицы S.
4. Пользователю разрешен доступ к записям каталога, т. е. к строкам таблицы SYSTABLES, только для таблиц, созданных этим пользователем:
CREATE VIEW МОИ_ТАБЛИЦЫ
AS SELECT *
FROM SYSIBM.SYSTABLES
WHERE CREATOR = USER;
Ключевое слово USER (пользователь) обозначает системную переменную, значение которой представляет собой ИД санкционирования. Оно может входить во фразу SELECT, во фразу WHERE, во фразу SET предложения UPDATE, либо как вставляемое значение — в предложение INSERT. Идентификатор санкционирования в запросе — это ИД санкционирования для пользователя, исполняющего фразы SELECT или WHERE (либо предложения UPDATE или INSERT), в которые он входит. В приведенном примере, следовательно, он представляет не ИД пользователя, который создает это представление, а ИД пользователя, который использует это представление. Если, например, пользователь xyz издает предложение:
SELECT *
FROM МОИ_ТАБЛИЦЫ;
то DB2, а фактически генератор планов прикладных задач, по существу, преобразует это предложение в следующее:
SELECT *
FROM SYSIBM.SYSTABLES
WHERE CREATOR = 'xyz';
Аналогично представлению из приведенного выше первого примера, это представление является «горизонтальным подмножеством» лежащей в основе базовой таблицы. Однако в данном примере различные пользователи видят здесь различные подмножества. Фактически эти подмножества не пересекаются ни для каких двух пользователей. Такие подмножества иногда называются контекстно-зависимыми.
5. Пользователю разрешен доступ к средним объемам поставок по поставщикам, но не к каким-либо индивидуальным объемам поставок:
CREATE VIEW AVG (НОМЕР_ПОСТАВЩИКА, СРЕДНИЙ_ОБЪЕМ)
AS SELECT НОМЕР_ПОСТАВЩИКА, AVG (КОЛИЧЕСТВО)
FROM SP
GROUP BY НОМЕР_ПОСТАВЩИКА;
Пользователи этого представления видят статистическую сводку лежащей в основе базовой таблицы S.
Примечание.
Создатель приведенных выше представлений должен иметь по крайней мере привилегию на исполнение предложения SELECT над всеми таблицами, на которые ссылаются определения этих представлений. Привилегии доступа обсуждаются в следующем разделе.
Как показывают приведенные примеры, механизм представлений системы DB2 «задаром» обеспечивает очень важные средства безопасности — «задаром» во всяком случае потому, что механизм представлений включен в систему для иных целей, как указывалось в главе 8. Более того, многие проверки полномочий доступа, даже проверки, зависимые от значений, могут осуществляться на стадии компиляции (во время связывания), а не на стадии исполнения, что обеспечивает существенный выигрыш производительности. Однако подход к безопасности, основанный на представлениях, иногда оказывается несколько тяжеловесным, в частности, если некоторому конкретному пользователю необходимы различные привилегии доступа к различным подмножествам одной и той же таблицы в одно и то же время. Рассмотрим следующий пример. Предположим, что данному пользователю разрешена выборка (операция
SELECT) рейтингов, т. е. значений состояния, для всех поставщиков, а обновлять их (операция UPDATE) разрешается только для поставщиков из Парижа. Тогда потребуется два следующих представления:
|
CREATE
|
VIEW
|
ВСЕ_РЕЙТИНГИ
|
CREATE
|
VIEW
|
ПАРИЖСКИЕ_
РЕЙТИНГИ
|
AS
|
SELECT
|
НОМЕР_
ПОСТАВЩИКА, СОСТОЯНИЕ
|
AS
|
SELECT
|
НОМЕР_
ПОСТАВЩИКА, СОСТОЯНИЕ
|
|
FROM
|
S;
|
|
FROM
|
S
|
|
|
|
|
WHERE
|
ГОРОД=' ПАРИЖ';
При этом операции
SELECT могут быть адресованы представлению ВСЕ_РЕЙТИНГИ, а операции обновления — только представлению ПАРИЖСКИЕ_РЕЙТИНГИ. В связи с этим программирование становится довольно невразумительным. В этом можно, например, убедиться, рассматривая структуру программы, которая просматривает и печатает рейтинги всех поставщиков, а также обновляет некоторые из них (рейтинги поставщиков из Парижа), когда это требуется.
Другой недостаток связан с тем, что при вставке (операция INSERT) или обновлении (операция UPDATE) записей при помощи представления система DB2 не требует, чтобы новая или обновленная запись удовлетворяла предикату, определяющему это представление. Такое требование можно ввести с помощью спецификации CHECK, но эта возможность, как пояснялось в главе 8, не всегда может быть использована и во всяком случае это факультативная возможность — пользователь не обязан
ее специфицировать. Таким образом, приведенное выше представление ПАРИЖСКИЕ_ПОСТАВЩИКИ, например, может не дать пользователю возможности видеть поставщиков, которые находятся не в Париже, но при отсутствии спецификации CHECK оно не может помешать пользователю создать такого поставщика или переместить какого-либо существующего парижского поставщика в некоторый другой город. Такая операция, конечно, приведет к тому, что новая или обновленная запись немедленно исчезнет из этого представления, но она однако же появится в соответствующей базовой таблице.
ПРЕДВАРИТЕЛЬНЫЕ ЗАМЕЧАНИЯ
Прежде чем мы сможем перейти к рассмотрению предложений встроенного языка SQL самих по себе, необходимо предварительно обсудить некоторые детали. Большинство из них иллюстрируется фрагментом программы, показанным на рис. 10.1. ( Здесь и далее в переводе мы отступаем от синтаксиса языка ПЛ/1, не предусматривающего использование букв русского алфавита в идентификаторах. Это же замечание относится, впрочем, и к языку SQL.— Примеч. пер.)
Рассматривая этот пример, нетрудно установить следующее:
1. Предложениям встроенного SQL всегда предшествует ЕХЕС SQL, так что их можно легко отличить от предложений включающего языка, а завершаются они следующим образом:
в ПЛ/1 — точка с запятой
в Коболе — END ЕХЕС
в Фортране — отсутствие символа продолжения в колонке 6
в языке Ассемблера — отсутствие символа продолжения в колонке 72.
2. Исполняемые
предложения SQL (далее для краткости слово «встроенный» обычно опускается) могут использоваться во всех тех случаях, когда могут использоваться исполняемые предложения включающего языка. Обратим внимание здесь на уточнитель «исполняемые». В отличие от интерактивного SQL встроенный SQL включает некоторые предложения, которые являются чисто декларативными, неисполняемыми. Например, DECLARE TABLE (объявить таблицу) не является исполняемым предложением, так же как и DECLARE CURSOR (объявить курсор),—см. раздел 10.4.
3. Предложения SQL могут содержать обращения к переменным включающего языка. Перед такими обращениями ставится двоеточие с тем, чтобы отличать их от имен полей SQL. Переменные включающего языка могут появляться в предложениях манипулирования данными языка SQL только в следующих местах:
— фраза INTO в предложении SELECT (результирующая величина, которой присваивается значение, выбираемое из базы данных)
DCL ЗАДАННЫЙ_НОМЕР CHAR (5);
DCL РАНГ FIXED BIN (15);
DCL ГОРОД CHAR (15);
DCL АЛЬФА . . . ;
DCL БЕТА . . . ;
ЕХЕС SQL DECLARE S TABLE
(НОМЕР_ПОСТАВЩИКА CHAR (5)
NOT NULL,
ФАМИЛИЯ CHAR (20),
СОСТОЯНИЕ SMALLINT,
ГОРОД CHAR (15));
ЕХЕС SQL INCLUDE SQLCA;
. . . . . . . . . . . . . . . . . . . . . . .
IF АЛЬФА > БЕТА THEN
GETSTC:
ЕХЕС SQL SELECT СОСТОЯНИЕ, ГОРОД
INTO :РАНГ,: ГОРОД
FROM S
WHERE НОМЕР_ПОСТАВЩИКА = : ЗАДАННЫЙ_НОМЕР;
. . . . . . . . . . . . . . . . . . . . . . .
PUT SKIP LIST (РАНГ, ГОРОД);
Рис. 10.1. Фрагмент программы на языке ПЛ/1 с предложениями встроенного SQL
— фраза SELECT (значение, выборку - которого нужно произвести)
— фраза WHERE в предложениях SELECT, UPDATE, DELETE (значение, которое следует сравнивать)
— фраза SET в предложении UPDATE (источник для обновляемого значения)
— фраза VALUES в предложении INSERT (источник для вставляемого значения)
— элемент арифметического выражения во фразах SELECT, WHERE или SET, но не VALUES, где в результате вычисления этого выражения в свою очередь определяется значение, которое подлежит выборке, сравнению или обновлению. Они могут появляться также в некоторых предложениях, относящихся только к встроенному языку (подробности приведены ниже). Они не могут появиться в каких-либо других предложениях SQL.
4. Любые используемые в программе таблицы (базовые таблицы или представления) должны быть объявлены при помощи предложения ЕХЕС SQL DECLARE для того, чтобы сделать программу в большей степени самодокументируемой и дать возможность прекомпилятору выполнять некоторые синтаксические проверки манипулятивных предложений.
5. После того как было выполнено любое предложение SQL, информация обратной связи возвращается программе в область, называемую областью связи SQL (SQLCA — SQL Communication Area). В частности, в поле области SQLCA, называемое SQLCODE, возвращается числовой индикатор состояния. Нулевое значение SQLCODE означает, что данное предложение выполнено успешно. Положительное значение означает, что предложение все же выполнено, но предупреждает, что имела место некоторая исключительная ситуация. Например, значение +100 указывает, что не было найдено никаких данных, удовлетворяющих запросу. Наконец, отрицательное значение указывает, что имела место ошибка, и данное предложение не было успешно выполнено. Поэтому в принципе за каждым предложением SQL в программе должна следовать проверка значения SQLCODE и должно предприниматься соответствующее действие, если это значение оказывается не тем, которое ожидалось. Но этот шаг не показан на рис. 10.1. Как указывается в разделе 10.5, на практике такое явное тестирование значений SQLCODE, возможно, не является необходимым. Область связи SQL включается в программу с помощью предложения
ЕХЕС SQL INCLUDE SQLCA;
6. Как уже упоминалось, предложение SELECT встроенного языка должно содержать фразу INTO, специфицирующую переменные включающего языка, которым должны быть присвоены значения, найденные в базе данных. Переменные во фразе INTO могут быть скалярными переменными (элементами) или структурами. Структура рассматривается просто как краткая запись списка элементов, составляющих эту структуру. Структуры могут использоваться также во фразе VALUES предложения INSERT.
7. Переменные включающего языка должны иметь типы данных, совместимые с типами данных языка SQL тех полей, с которыми они должны сравниваться, значения которых им должны быть присвоены, или которым должны быть присвоены значения этих переменных. Совместимость типов данных определяется следующим образом:
а) литерные данные SQL совместимы с литерными данными включающего языка, независимо от их длины и независимо от того, является ли какая-либо из этих длин переменной;
б) числовые данные SQL совместимы с числовыми данными включающего языка, независимо от основания системы счисления (десятичная или двоичная), способа представления (с фиксированной или плавающей точкой) и точности (число цифр). Система DB2 выполнит все необходимые преобразования. Если при присваивании значения в программе либо в предложении языка SQL имеет место потеря значащих цифр или литер, связанная с тем, что поле, принимающее значение, слишком мало, программе возвращается информация об ошибке.
8. Отметим, что переменные включающего языка и поля базы данных могут иметь одни и те же имена. Переменная включающего языка может быть элементом структуры. Например:
DCL 1 ДАНО,
2 НОМЕР_ПОСТАВЩИКА CHAR(5),
2 . . .;
ЕХEС SQL SELECT . . .
. . . . . . .
WHERE НОМЕР_ПОСТАВЩИКА =
:ДАНО. НОМЕР_ПОСТАВЩИКА;
Заметим, что в предложениях SQL используется уточнение имен в стиле ПЛ/1, а не Кобола (:ДАНО.НОМЕР_ПОСТАВЩИКА, а не НОМЕР_ПОСТАВЩИКА OF ДАНО), даже когда включающим языком фактически является Кобол.
Это все, что касается предварительных замечаний. В остальной части данной главы мы сосредоточим внимание, главным образом, на операциях манипулирования данными SELECT, UPDATE, DELETE и INSERT. Как уже указывалось, к большинству из этих операций можно обратиться довольно простым образом, т. е. лишь с небольшими изменениями в их синтаксисе. Однако предложения SELECT требуют особого рассмотрения. Проблема заключается в том, что исполнение предложения SELECT порождает таблицу—таблицу, которая, в общем случае, содержит множество записей, а такие языки, как Кобол и ПЛ/1, просто не обладают хорошими средствами, позволяющими оперировать одновременно более чем одной записью. По этим причинам необходимо обеспечить своего рода мост между уровнем множеств языка SQL и уровнем записей включающего языка. Такой мост обеспечивают курсоры.
Курсор — это новый вид объекта языка SQL, относящийся только к встроенному SQL, поскольку интерактивный SQL, конечно же, в нем не нуждается. Курсор состоит, по существу, из некоторого рода указателя,
который может использоваться для просмотра множества записей. Поочередно указывая каждую запись в данном множестве, он обеспечивает, таким образом, возможность обращения к этим записям по одной одновременно. Отложим, однако, детальное обсуждение курсоров до раздела 10.4, а сначала рассмотрим (в разделе 10.3) те предложения, для которых они не требуются.
ПРЕИМУЩЕСТВА ПРЕДСТАВЛЕНИЙ
Завершим эту главу краткой сводкой преимуществ представлений.
— Они обеспечивают определенную степень логической независимости данных, несмотря на реструктуризацию базы данных, как было пояснено в предыдущем разделе.
— Они дают возможность различным пользователям по-разному видеть одни и те же данные, возможно, даже в одно и то же время. Это соображение, очевидно, имеет важное значение, когда имеется много различных категорий пользователей и все они взаимодействуют с единой интегрированной базой данных.
— Упрощается пользовательское восприятие. Очевидно, что механизм представлений дает возможность пользователям сосредоточить внимание именно на тех данных, которые представляют для них интерес, и игнорировать остальные данные. Вместе с тем не настолько очевидно, что по крайней мере в отношении поиска данных этот механизм может также значительно упростить пользовательские операции манипулирования данными. В частности, поскольку для пользователя может быть предусмотрено представление, в котором все лежащие в его основе таблицы соединены вместе, необходимость явных операций для перехода от одной таблицы к другой может быть значительно уменьшена. В качестве примера рассмотрим представление ПАРЫ_ГОРОДОВ и сопоставим предложение SELECT, необходимое для нахождения городов, где хранятся поставляемые из Лондона детали, и использующее это представление, с предложением SELECT, требующимся для получения того же результата непосредственно из базовых таблиц. В действительности, сложный процесс выборки был перенесен здесь из сферы манипулирования данными в сферу определения данных. (На самом деле различия между этими двумя сферами в реляционных языках, подобных SQL, далеко не ясны.)
— Для скрытых данных автоматически обеспечивается секретность. «Скрытые данные» обозначает здесь данные, невидимые через некоторое заданное представление. Ясно, что такие данные защищены от доступа через это конкретное представление. Таким образом, принуждение пользователя осуществлять доступ к базе данных через представления является простым, но эффективным механизмом для управления санкционированием доступа. Этот аспект представлений более подробно обсуждается в следующей главе.
ПРЕИМУЩЕСТВА РЕЛЯЦИОННЫХ СИСТЕМ
Если нужно выразить преимущества реляционной системы, такой, как DB2, единственным словом, то это слово — простота, где под «простотой» мы понимаем главным образом простоту для пользователя. Простота в свою очередь трансформируется в применяемость и производительность. Применяемость означает, что даже сравнительно неквалифицированные пользователи могут использовать систему для выполнения полезной работы. Иначе говоря, конечные пользователи часто могут получать от системы полезные результаты, избегая при этом необходимости преодолевать потенциально узкие места, с которыми сталкивается подразделение обработки данных. Производительность означает, что как конечные пользователи, так и профессиональные специалисты в области обработки данных могут более продуктивно выполнять свои каждодневные обязанности. В результате они могут внести значительный вклад в решение известной проблемы невыполненного заказа на разработку приложения (см. ниже параграф «Разработка приложения»). В данном разделе обсуждаются некоторые факторы, способствующие простоте такой системы, как DB2.
Теоретическая основа
Первый фактор заключается в том, что реляционные системы основаны на формальном теоретическом фундаменте — на реляционной модели, подробно обсуждаемой в Приложении А. В результате такие системы ведут себя строго определенным образом, и пользователи, возможно, не осознавая этого факта, руководствуются простой моделью их поведения, которая позволяет с уверенностью предсказывать, что будет делать система в любой заданной ситуации. Нет или не должно быть никаких неожиданностей[25]. Такая предсказуемость означает, что этому пользовательскому интерфейсу легко обучать, его легко изучить, использовать и запомнить.
В частности, отметим, между прочим, что многие критики реляционных систем в прошлом высказывали возражения именно по этому вопросу. Смысл возражений заключался, по-видимому, в том, что лишь теоретики способны понять или нуждаются в понимании чего-либо, что основано на теории. Наша точка зрения совершенно противоположна: системы, не основанные на теории, весьма трудны для понимания. Без преувеличения можно сказать, что «теоретический» вовсе не означает «не практичный». Наоборот, соображения, которые сначала отвергаются как «только теоретические» (!), имеют скверную привычку несколько лет спустя становиться чрезвычайно практичными.
Небольшое число понятий
Реляционная модель выделяется среди других моделей данных благодаря небольшому числу используемых в ней понятий. Как указывалось в главе 6, все данные в реляционной базе данных представляются одним и только одним способом, а именно как значения в столбцах и строках некоторых таблиц, и для каждой из четырех основных функций (выборка, изменение, вставка, удаление) необходим, следовательно, только один оператор. По тем же самым причинам требуется меньше операторов для всех других функций — для определения данных, обеспечения безопасности данных и санкционирования доступа, отображения в среду хранения и т. д.,—чем это необходимо в нереляционных системах. В частности, в случае санкционирования доступа простота и регулярность структуры данных дают возможность определить достаточно утонченный механизм защиты данных. При таком механизме, как отмечалось в главе 9, могут быть легко определены и удобным образом реализованы зависимые и независимые от значений данных, контекстно-зависимые и другие ограничения.
Самостоятельное значение имеет факт, связанный с указанным выше, и заключающийся в том, что в реляционной модели различные понятия четко разделены и не переплетаются сложными взаимосвязями. Напротив, конструкция связи типа владелец— член или отец — сын, встречающаяся во многих нереляционных системах, образует сложную взаимосвязь нескольких существенно различных понятий. Она одновременно является представлением связи вида один-ко-многим, путем доступа или совокупностью путей доступа, механизмом для реализации определенных ограничений целостности и т. д. В результате становится трудно установить, какой цели служит данная связь, и она может использоваться для таких целей, для которых она не была предназначена. Например, программа может воспользоваться некоторым путем доступа, появление которого в действительности является побочным эффектом того способа, который был выбран проектировщиком базы данных для представления определенного ограничения целостности. Если же потребуется изменить это ограничение, то необходимо будет произвести реструктуризацию базы данных. При этом с большой вероятностью потребуется также переписать данную программу, даже если она совершенно не заинтересована в рассматриваемом ограничении целостности как таковом.
Операции над множествами
Реляционные операции манипулирования данными, например SELECT, UPDATE и т. д., в языке SQL являются операциями над множествами. Этот факт означает, что пользователи должны просто специфицировать, что они хотят, а не как получить то, что они хотят. Например, пользователь, которому требуется узнать, какие детали поставляются поставщиком S2, просто выдает на языке SQL запрос:
SELECT НОМЕР_ДЕТАЛИ
FROM SP
WHERE НОМЕР_ПОСТАВЩИКА ='S2';
Система DB2 принимает решение, каким образом осуществить навигацию в физической структуре данных на диске для того, чтобы ответить на этот запрос. По этой причине подобные DB2 системы, как уже упоминалось в главе 1, часто характеризуются как системы с «автоматической навигацией». Напротив, системы, в которых пользователи должны сами осуществлять такую навигацию, характеризуются как системы с «ручной навигацией». Избавляя пользователя от этих забот, система DB2 позволяет ему сосредоточиться на решении настоящей задачи, т. е. в данном случае, на поиске ответа на запрос и использовании этой информации для какой-либо цели, где она необходима, во внешнем мире. В случае конечных пользователей фактически именно благодаря автоматической навигации обеспечивается возможность использования системы. Нетрудно найти такой пример запроса на языке SQL, для которого эквивалентная программа на Коболе занимала бы десять или двадцать страниц, и о написании такой программы для большинства пользователей не могло бы быть и речи, а может быть она и не стоила бы необходимых для этого усилий.
Кроме того, средствами системы для автоматической навигации могут точно так же, как конечные пользователи, воспользоваться прикладные программисты. Поэтому результативность работы прикладных программистов в реляционной системе также может быть более высокой.
Язык, используемый в двух режимах
Один и тот же язык SQL используется в системе DB2 как для программирования, так и для интерактивного доступа к базе данных. Из этого факта непосредственно следует:
1. Все пользователи различных категорий — системные администраторы и администраторы баз данных, прикладные программисты, конечные пользователи с разным уровнем подготовки — по существу, используют один и тот же язык и поэтому способны лучше общаться друг с другом. Пользователю легко также переходить из одной категории в другую — в одном случае выполнять функции администратора по определению данных, а в другом — функции конечного пользователя по спецификации специальных запросов.
2. Прикладные программисты могут отлаживать записанные на SQL части их программ через интерактивный интерфейс (SPUFI или, возможно, QMF). Этот момент несколько подробнее обсуждался в разделе 12.4.
Независимость данных
Независимость данных — это независимость пользователей, и пользовательских программ от некоторых подробностей способа хранения и доступа к данным. Она имеет важное значение по крайней мере по двум причинам:
1. Для прикладных программистов она важна, поскольку без этого изменения в структуре базы данных приводят к соответствующим изменениям в прикладных программах. При отсутствии такой независимости происходит одно из двух: либо становится почти невозможно сделать требуемые изменения в базе данных из-за капиталовложений в существующие программы, либо, что более вероятно, значительная часть усилий по прикладному программированию посвящается исключительно сопровождению, т. е. такой эксплуатационной работе, необходимость в которой была бы исключена, если бы система обеспечивала независимость данных. Оба этих фактора в значительной степени способствуют возникновению проблемы невыполненного заказа на разработку приложения, о которой упоминалось во введении к данному разделу.
2. Она важна и для конечных пользователей, поскольку без этого непосредственный доступ конечного пользователя к базе данных вообще едва ли был бы возможен. При этом независимость данных и очень высокий уровень таких языков, как SQL, дополняют друг друга.
Независимость данных не является неким абсолютом — различные системы обеспечивают ее в различной степени. (Иными словами, существуют системы, которые вообще не обеспечивают независимости данных. Это как раз и означает, что некоторые системы в большей мере зависимы от данных, чем другие.) Кроме того, термин «независимость данных» в действительности охватывает два несколько разных понятия, а именно: понятие физической независимости данных, т. е. независимости физической организации данных в среде хранения, и понятие логической независимости данных, т. е. независимости логической структуры данных как таблиц и полей. Система DB2 достаточно развита в обоих аспектах, хотя, без сомнения, еще есть поле деятельности для ее развития и в той и в другой областях. Так, например, жаль, что логическое понятие принудительной уникальности взаимосвязано с физическим понятием индекса. По существу, DB2 обеспечивает физическую независимость данных благодаря ее возможностям автоматической навигации и автоматического связывания (для того, чтобы вспомнить об автоматическом связывании, см. раздел 2.2). Подобным же образом она обеспечивает логическую независимость данных благодаря ее механизму представлений (более подробно об этом см. раздел 8.5).
Разработка приложений
Системы, подобные DB2, в целом ряде аспектов облегчают процесс разработки приложений.
1. Во-первых, возможности спецификации специализированных запросов и генерации отчетов означают, что вообще может отсутствовать необходимость разработки прикладных программ в традиционном понимании этого термина. Важность этого фактора трудно переоценить. Одна из реляционных систем (здесь нет возможности назвать ее, но это не какая-нибудь малозначащая система) обладает единственной традиционной прикладной программой. Все остальное делается с помощью препроцессорных системных средств обработки запросов и генерации отчетов.
2. Во-вторых, обеспечение высокой степени независимости данных вместе с высоким уровнем операций манипулирования данными означает, что если программу писать все-таки нужно, то писать ее легче, она требует меньше усилий для сопровождения и ее легче изменять, если в этом действительно возникает необходимость, чем это было бы в более старых нереляционных системах.
3. В-третьих, и это в большой степени является следствием указанного в предыдущем пункте, цикл разработки приложения может гораздо в большей мере, чем это обычно делается, вовлекать макетирование: первая версия может быть создана и показана предполагаемым пользователям, которые имеют далее возможность предложить некоторые улучшения для включения в следующую версию и т. д. В результате окончательный вариант приложения будет в точности соответствовать потребностям пользователя. Общий процесс разработки становится значительно менее жестким, чем обычно, и пользователи приложения могут в гораздо большей степени вовлекаться в этот процесс на пользу всем заинтересованным.
Динамическое определение данных
Преимущества динамического определения данных уже подробно обсуждались в главе 3 (см. раздел 3.4), и мы не будем здесь повторять эти аргументы. Однако отметим здесь одно дополнительное обстоятельство. Способность в любое время создавать новые определения, не требуя для этого остановки системы,— в действительности только одна из составных частей более крупной общей задачи, состоящей в том, чтобы вообще исключить необходимость каких-либо запланированных остановок системы. При этом, например, утилиты можно вызывать с работающего в интерактивном режиме терминала, и они могут исполняться параллельно с решением основных задач. Можно, например, делать копию содержимого базы данных несмотря на то, что она одновременно обновляется некоторыми транзакциями. В идеальном случае систему нужно будет стартовать только один раз, когда она впервые устанавливается, и далее она должна будет функционировать «вечно». Мы, однако, не утверждаем, что указанная задача уже решена.
Легкость установки и легкость эксплуатации
Система DB2 разрабатывалась таким образом, чтобы она была, по возможности, легкой для установки и эксплуатации. Достижению этой цели способствует ряд возможностей системы, некоторые из которых были рассмотрены выше в данном разделе. Подробное обсуждение таких возможностей, помимо тех, что уже обсуждались в предыдущих главах, выходит за рамки данной книги. Однако целесообразно явным образом указать одно весьма важное следствие, вытекающее из них, а именно: для того, чтобы предоставить услуги системы DB2 весьма большой группе пользователей (прикладных программистов и конечных пользователей), требуется лишь сравнительно маленькая группа профессиональных специалистов в области обработки данных (администраторов, системных программистов, работающих за консолью операторов). DB2—чрезвычайно экономичная система.
Проектирование баз данных
В реляционной системе проектировать базы данных легче, чем нереляционной, по ряду причин, хотя при этом в сложных ситуациях могут потребоваться некоторые трудные решения. Во-первых, разделение логического и физического уровней означает, что проблемы логического и физического проектирования можно решать по отдельности. Во-вторых, существует ряд надежных принципов, которые могут быть использованы для решения проблемы логического проектирования. В-третьих, возможности динамического определения данных и высокая степень независимости данных опять-таки означают, что нет необходимости одновременно разрабатывать весь проект, и что не настолько критична потребность в получении его прямо с первого раза. Вопрос о проектировании баз данных для системы довольно подробно обсуждается в Приложении В.
Интегрированный каталог
Как уже указывалось в главе 7, каталог в системе DB2 полностью интегрирован с остальными данными в том смысле, что он представлен точно таким же образом (в виде таблиц) и что его содержимое можно запрашивать точно таким же образом (с помощью SQL). Иными словами, нет никаких искусственных и ненужных различий между данными каталога и другими данными или между данными и «данными о данных» (или «метаданными», как их иногда называют). Такая интеграция обеспечивает ряд преимуществ, в том числе:
1. Поиск чего-либо в базе данных и поиск чего-либо в каталоге — это один и тот же процесс. Для того чтобы усмотреть здесь преимущество, рассмотрим аналогичную ситуацию — поиск чего-либо в книге и поиск чего-либо в оглавлении этой книги. Было бы очень досадно, если бы это оглавление оказалось бы где-либо в ином месте, а не в самой этой книге, и в формате, который бы требовал несколько иного способа доступа, например, если бы оглавление было бы на испанском языке и хранилось бы на карточках размером 3 на 5, в то время как сама книга была бы на английском языке. Роль каталога по отношению к базе данных совершенно аналогична роли оглавления по отношению к книге.
2. Значительно упрощается процесс создания универсальных, т. е. управляемых «метаданными», прикладных программ. Допустим, например, что требуется написать программу, которая проверяет, чтобы значение номера поставщика, появляющееся где-либо в базе данных, входило бы также в столбец НОМЕР_ПОСТАВЩИКА таблицы поставщиков S — разумное само по себе требование. Необходимо при этом, чтобы рассматриваемая программа выполняла свои функции без каких-либо предварительных предположений о структуре базы данных, т. е. в программу не должны быть встроены какие-либо знания относительно того, какие существуют таблицы и какие в них столбцы. В более общем виде предположим, что нужно написать программу, которая бы проверяла, что каждое появляющееся где-либо в базе данных значение типа Х появляется также в некотором специфицированном столбце Y некоторой специфицированной таблицы Z, где X, Y и Z — параметры. И снова здесь не принимается каких-либо предварительных предположений о структуре базы данных. В обоих этих примерах решающее значение имеет интегрированный каталог. Примечание. Такие программы были бы очень нужны на практике. См. Приложение В, раздел В.7.
ПРИМЕРЫ ЗАПРОСОВ
Начнем с простого примера — с запроса «Выдать номера и состояния для поставщиков, находящихся в Париже». Этот запрос может быть выражен в SQL следующим образом:
SELECT НОМЕР_ПОСТАВЩИКА, СОСТОЯНИЕ
FROM S
WHERE ГОРОД = 'Париж';
В качестве результата получим:
|
НОМЕР_ПОСТАВЩИКА
|
СОСТОЯНИЕ
|
S2
S3
|
10
30
Этот пример иллюстрирует самую общую форму предложения SELECT в языке SQL—
"SELECT (выбрать) специфицированные поля
FROM (из) специфицированной таблицы
WHERE (где) некоторое специфицированное условие является истинным"
Заметим, что результатом запроса является другая таблица — таблица, которая некоторым образом получается из заданных в базе данных таблиц. Иными словами, в реляционной системе типа DB2 пользователь всегда действует в рамках простой табличной структуры, и это—весьма привлекательная особенность таких систем [11].
В данном случае было бы вполне возможно сформулировать запрос, используя уточненные имена полей:
SELECT S.HOMEP_ПОСТАВЩИКА, S. СОСТОЯНИЕ
FROM S
WHERE S ГОРОД = 'Париж';
Использование уточненных имен никогда не рассматривается как ошибка, и иногда это существенно, как мы увидим в разделе 4.3. Для справочных целей ниже показана общая форма предложения SELECT, в которой, однако, опущена возможность UNION, обсуждаемая в следующей главе:
SELECT [DISTINCT] элемент(ы)
FROM таблица (или таблицы)
[WHERE предикат]
[GROUP BY поле (или поля) [HAVING предикат] ]
[ORDER BY поле (или поля) ];
Перейдем теперь к иллюстрации основных особенностей этого предложения с помощью весьма продолжительной серии примеров. Примечание. Фразы GROUP BY (группировать по) и HAVING (имея) обсуждаются в главе 5. Со всеми остальными фразами читатель по крайней мере познакомится в этой главе, хотя рассмотрение более сложных их аспектов также отложено до главы 5.
Ряд других программных продуктов фирмы
Ряд других программных продуктов фирмы IBM является более или менее тесно связанным с DB2. Основные из них рассматриваются ниже.
SQL/DS (Structured Query Language/Data System)
Как уже указывалось, SQL/DS — это реляционная СУБД для операционных систем DOS/VSE и VM/CMS. Она принадлежит «семейству» DB2 в том смысле, что в обеих системах используется по существу один и тот же язык SQL. Если говорить точнее, в обеих системах — одни и те же предложения манипулирования данными и большинство предложений определения данных, которые различаются некоторыми незначительными деталями. Однако формат хранимых данных в этих системах не одинаков, но предоставляются утилиты, помогающие осуществлять передачу данных из базы данных SQL/DS в базу данных DB2 и наоборот[4].
Примечание. SQL/DS включает как части базового продукта:
а) интерактивный интерфейс запросов и генератора отчетов, называемый ISQL («Interactive SQL»); и
б) средство «DL/1 Extract» для копирования специфицированных данных из базы данных DL/1-DOS в базу данных SQL/DS, так что к ним можно осуществлять доступ через интерфейс ISQL (DL/1-DOS является по существу урезанной версией системы IMS для операционной системы DOS/VSE. DL/1—язык доступа К базам данных, используемый как в DL/1-DOS, так и в IMS).
В отношении указанных возможностей DB2 в определенной мере отличается от SQL/DS. Базовый продукт DB2 также включает интерактивный интерфейс, в некоторой степени близкий к ISQL, называемый DB2I («DB2 Interactive»). Однако DB2I в действительности предназначен для профессионалов в области обработки данных, например для прикладных программистов, а не для случайных пользователей. Настоящий интерфейс для конечных пользователей DB2 обеспечивается отдельным периферийным продуктом, называемым QMF (см. подробности ниже). Аналогично, функции «DL/1 Extract» реализуются в обстановке DB2 другим отдельным продуктом — DXT (и снова подробности см. ниже).
QMF (Query Management Facility)
QMF (Query Management Facility) — развитое периферийное средство спецификации запросов и генерации отчетов как для DB2 (под TSO), так и для SQL/DS (под DOS/VSE или VM/CMS).
Заметим, Что это отдельный программный продукт. С точки зрения DB2 это фактически не что иное, как интерактивное приложение TSO. QMF позволяет конечным пользователям вводить случайные
запросы либо на языке SQL, либо на языке QBE (Query-By-Example), и продуцировать разнообразные форматизированные отчеты из результатов обработки таких запросов. Он похож, таким образом, на встроенный интерфейс спецификации запросов/генерации отчетов ISQL, предоставляемый SQL/DS в качестве части базового продукта. Однако предоставляемый QMF диапазон возможностей значительно превосходит возможности ISQL. В частности, ISQL не поддерживает языка QBE.
Более подробная информация о QMF приводится в главе 15.
DXT (Data Extract)
DXT (Data Extract) — это универсальная программа копирования данных. Она позволяет скопировать в последовательный файл специфицированное подмножество данных заданной базы данных системы IMS либо набора данных VSAM или SAM. При этом копирование осуществляется в формате, подходящем для загрузки (с помощью соответствующей утилиты загрузки) в базу данных системы DB2 либо SQL/DS. В главе 15 содержится более подробная информация относительно DXT.
ПРОИЗВОДИТЕЛЬНОСТЬ
В последние несколько лет в области обработки данных сложился ряд ошибочных представлений, касающихся реляционных систем, большинство из которых связано с их производительностью. Очень часто можно услышать два таких мнения:
«Все реляционные системы очень хороши для обработки специальных запросов, но они никогда не достигнут уровня производительности, требуемого для производственных систем (или систем обработки транзакций или ...)».
«Для того чтобы реляционные системы были способны достигнуть приемлемой производительности, нужны новые достижения в технологии аппаратного обеспечения, например аппаратная реализация ассоциативной памяти».
Противоположное мнение, которого придерживается и автор, заключается в следующем:
«Нет никакой внутренней причины, благодаря которой производительность реляционной системы должна быть сколько-нибудь ниже — или, в действительности, сколько-нибудь выше (!) — чем у системы какого-либо иного типа».
Обсудим и попытаемся обосновать это мнение.. Отметим прежде всего, что двумя основными характеристиками производительности являются число операций ввода-вывода и продолжительность обработки (объем работы центрального процессора). Рассмотрим каждую из них поочередно.
Продолжительность обработки
DB2 — система компилирующего типа, точно так же, как и SQL/DS. Большинство других систем, реляционных или другого типа, во время написания этой книги являются системами интерпретирующего типа. Однако преимущества компиляции получили широкое признание, и известно, что в направлении подхода, основанного на компиляции, развивается несколько других реляционных систем. Преимущество компиляции заключается именно в том, что она уменьшает продолжительность обработки на стадии исполнения. При этом на стадии исполнения исключаются все перечисленные ниже операции:
— синтаксический анализ первоначального запроса
— обнаружение синтаксических ошибок и выдача сообщений о них
— отображение имен логического уровня в адреса физического уровня
— выбор стратегии доступа
— проверка полномочий доступа
— генерация машинного кода.
Наиболее важной из этих операций является, вероятно, выбор стратегии доступа, или, иными словами, оптимизация. Таким образом, в случае компиляции продолжительность обработки на стадии исполнения значительно короче, чем она была бы в иных случаях. Немаловажно также, что при компиляции машинный код генерируется для конкретного исходного запроса, и поэтому он может оказаться более эффективным, чем более универсальный код, используемый в режиме интерпретации. Более того, система достигает этого преимущества компиляции в производительности, как уже указывалось в главе 2, без какой-либо соответствующей потери гибкости в функционировании: если становится необходимой перекомпиляция, например, в случае, когда уничтожен какой-либо индекс, то система осуществляет ее автоматически («автоматическое связывание»).
Заметим, между прочим, что компиляция в том смысле, как этот термин понимается в системе DB2, т. е. оптимизированная компиляция, не была бы осуществима в системе, ориентированной на обработку записей, поскольку такая система просто неспособна подобным же образом воспринимать намерения пользователя. Понятно поэтому, что реляционная система в конечном счете может обеспечить меньшую продолжительность обработки, чем нереляционная, если, например, нереляционная система всегда должна будет осуществлять синтаксический анализ запросов на стадии исполнения.
Операции ввода-вывода
Число операций ввода-вывода, требуемых для обработки конкретного запроса, является функцией физической
структуры базы данных, а не ее логической структуры. Иными словами, оно не имеет ничего общего с тем, каким образом база данных воспринимается ее пользователями — как реляционная или как некоторая другая структура. Поэтому можно разбить вопрос о том, сколько операций ввода-вывода требуется в реляционной системе, на два составляющих вопроса:
1. Способны ли поддерживаемые данной системой физические структуры обеспечить некоторый требуемый уровень производительности операций ввода-вывода?
2. Если ответ на первый вопрос положителен, то способна ли данная система принимать реляционные запросы высокого уровня, например предложения SELECT, и преобразовывать их в операции над такими физическими структурами, настолько же эффективные, насколько написанная вручную программа, т. е. программа, которая была бы составлена квалифицированным программистом, работающим непосредственно на физическом уровне?
В связи с первым вопросом нужно отметить, что в большинстве реляционных систем в настоящее время поддерживаются индексы, имеющие структуру В-деревьев. В некоторых системах, помимо этого, поддерживается техника хеширования и т. п., однако DB2 не относится к их числу. Фактически мало сомнения в том, что если должна быть выбрана единственная структура, то, очевидно, будут выбраны организованные в виде В-деревьев индексы. Далее, индексы с такой организацией, несомненно, способны обеспечить адекватный многим приложениям уровень производительности. Это утверждение должно быть справедливым, иначе никто не использовал бы VSAM. С другой стороны, справедливо также, что имеются некоторые приложения, для удовлетворения требований которых к производительности следует просто использовать, например, хеширование. Таким образом, ответ на первый вопрос, что касается системы DB2, положителен, если индексы приемлемы для рассматриваемого приложения, и отрицателен — в противном случае. (Конечно, и в этой ситуации ответ может быть все же положительным для некоторых других реляционных систем.)
Рассмотрим теперь второй вопрос (может ли данная система продуцировать программу, которая в такой же мере эффективна, как и программа, составленная вручную?), предполагая, что ответ на первый вопрос положителен. Краткий ответ — «да, может» (во многих, но не во всех случаях). Функция оптимизатора системы DB2 заключается именно в том, чтобы преобразовывать предложения SQL в оптимизированную машинную программу, где «оптимизированная» означает, главным образом, что сгенерированная программа использует лучшую из возможных стратегий для обработки первоначального запроса. Например, если задан запрос из раздела 16.2—«Выдать номера деталей, поставляемых поставщиком S2» — то в сгенерированной программе будет использоваться индекс по номерам поставщиков для таблицы SP, а не последовательный просмотр этой таблицы, конечно, в предположении, что такой индекс существует. Разумеется, не для каждого возможного запроса оптимизатор продуцирует наилучшую возможную программу. Но с другой стороны, этого не делает и большинство программистов. Кроме того, заметим, что здесь говорится о первой версии нового программного продукта. Естественно ожидать, что в процессе эксплуатации будут продолжаться его усовершенствования в области оптимизации. В действительности область оптимизации в базах данных в настоящее время это нечто, аналогичное оптимизации в языках программирования, какой она была примерно пятнадцать лет назад. Многочисленные исследователи занимаются этой проблемой в университетах и других организациях, и плоды этой деятельности, несомненно, найдут свое место в реализованных программных продуктах. Подобные усовершенствования могут быть осуществлены при этом так, чтобы они каким-либо образом не затрагивали форму внешнего интерфейса (это приблизительно и есть то, что представляет собой независимость данных).
На самом деле, понятно, что оптимизатор мог бы продуцировать лучшую программу, чем написанная вручную. Дело заключается в том, что оптимизатору доступна информация, касающаяся, например, физической кластеризации данных, размеров таблиц, избирательности индексов и т. д., которой обычно не обладает программист, разрабатывающий программу вручную. Кроме того, эта информация со временем может изменяться. В такой ситуации может возникать необходимость в повторной оптимизации. Выполнение ее в системе, подобной DB2, имеет тривиальный характер — достаточно просто выполнить операцию REBIND. В системе с ручным программированием это было бы весьма трудно сделать.
В связи с этим отметим еще один заключительный момент, касающийся оптимизации. Имеется другая причина, в связи с которой реляционная система может в некоторых случаях превосходить нереляционную по производительности. Эта причина состоит как раз в том, что система типа DB2 является оптимизирующей. Реляционные операции высокого уровня удается оптимизировать именно благодаря их высокому уровню — они содержат много семантики, и поэтому оптимизатор способен распознать, что же пытается сделать пользователь, и способен среагировать на это оптимальным образом. В противоположность этому в нереляционной системе, в которой пользователь действует на уровне записей, а не на уровне множеств, стратегии доступа выбираются самим пользователем. Если при этом пользователь сделает ошибочный выбор, то имеется мало шансов, что система будет способна оптимизировать такую пользовательскую программу. Предположим, например, что пользователь в действительности пытается вычислить соединение двух таблиц А и В. Существуют две возможные стратегии: а) поочередно для каждой записи из А найти все соответствующие ей записи в В; б) поочередно для каждой записи из В найти все соответствующие ей записи в А. В зависимости от относительных размеров А и В и от характеристик их физической кластеризации одна из этих стратегий может, вероятно, превзойти по производительности другую на несколько порядков величины. И если, как указывалось ранее, пользователь выберет ошибочную стратегию, то в действительности пет никакого способа, позволяющего системе заменить ее на другую, поскольку выбор пользователя выражается в виде последовательности операций низкого уровня, а не единственной операции высокого уровня.
Из всего сказанного можно сделать вывод, что нет абсолютно никакой причины для того, чтобы реляционная система, которая реализована на совершенно обычном оборудовании, использующем совершенно стандартную технику программного обеспечения, не функционировала вполне приемлемым образом. И вовсе не обязательно ждать новых достижений в разработке аппаратных средств, хотя если, например, ассоциативная память большой емкости па чипах когда-либо действительно стала бы коммерческой реальностью, несомненно, ею легче было бы воспользоваться в реляционной системе, чем в нереляционной.
Предостережение.
Для строгости заметим, что все предыдущие рассуждения были очень общими. В частности, не говорилось, что DB2 способна обеспечивать такую же производительность, как и какая-либо уже давно созданная система, например IMS. Пока еще слишком рано даже давать какие-либо оценки производительности системы DB2, хотя можно заключить беспроигрышное пари по поводу того, что любые такие оценки были бы существенно менее привлекательны, чем соответствующие оценки для IMS. Не приходится сомневаться в том, что для заданного приложения, где структуры данных и образцы транзакций заблаговременно хорошо изучены, какая-либо существующая система, например IMS, может быть конфигурирована и настроена в соответствии с требованиями заказчика таким образом, что она будет обеспечивать значительно более внушительную производительность, чем может обеспечить в настоящее время система DB2. С другой стороны:
а) Система, настроенная в соответствии с требованиями заказчика, будет выглядеть не настолько внушительной, когда к ней станут добавляться другие приложения. Реализация приложения 2 в обстановке системы, которая настроена на приложение 1, подобна рубке дерева поперек волокна — мешают делу чуждые намерения.
Заметим, что речь идет здесь не только о производительности, но также и о логическом уровне системы. Имеется в виду, что приложение 2, вероятно, будет также менее удобно писать. Логические структуры данных в нереляционной системе имеют тенденцию подвергаться влиянию одних приложений вопреки другим именно в связи с тем, что они подробно отражают физическую структуру данных. Логические структуры данных в реляционных системах, напротив, более нейтральны. Специфика приложения проявляется не в логической структуре данных, а в манипулятивных операциях, которые по определению являются значительно более гибкими, чем сравнительно статичная структура данных. Эта специфика будет, конечно, проявляться и в физической структуре данных.
б) Одна из причин преимущества нереляционных систем в производительности заключается просто в том, что эти системы эксплуатируются уже в течение десяти —пятнадцати лет и на протяжении этого времени постоянно усовершенствовались и настраивались. Реляционные системы также будут усовершенствоваться в течение следующих нескольких лет. Кроме того, неясно, возможны ли дальнейшие значительные усовершенствования нереляционных систем. В то же время, как указывалось ранее, имеется широкое поле деятельности для таких усовершенствований в реляционном случае.
в) Если даже нереляционная система обеспечивает на стадии исполнения более высокую производительность, ценность такого преимущества должна быть в первую очередь сбалансирована с затратами времени, необходимыми для приведения системы в работоспособное состояние. Капиталовложения на установку будут значительно быстрее окупаться для реляционной системы, поскольку значительно скорее начнут эксплуатироваться приложения. Конечная прибыль на капиталовложения может быть также более высокой при реляционной версии, если срок жизни данного приложения меньше, чем время, необходимое для того, чтобы нереляционная версия «догнала» его, говоря экономическим языком.
Повторяем, однако, что все сказанное выше — это теоретические рассуждения. Дело в том, что в настоящее время совершенно маловероятно, чтобы система типа DB2 была способна достигнуть уровня производительности системы типа IMS. Компромисс, который следует принимать во внимание в настоящее время — это производительность против применяемости или, другими словами, производительность машины против производительности человека. Общеизвестно, что стоимость человеческого труда быстро растет, а стоимость машинного времени также быстро снижается. В результате производительность человеческого труда очень быстро становится во многих приложениях доминирующим фактором, и, в действительности, во многих случаях это уже имеет место. Очевидно, что для таких приложений идеально подходят реляционные системы даже при их существующем уровне производительности. Имеется, однако, также и ряд приложений, для которых представляет пока преобладающий интерес производительность собственно оборудования. Поэтому системы типа IMS должны будут еще играть важную роль на протяжении нескольких лет. И если даже реляционные системы в конечном счете действительно достигнут паритета в отношении производительности, огромные капиталовложения в нереляционные системы являются фактором, обеспечивающим продолжение существования этих систем в обозримом будущем. Несомненно, это одна из причин, по которой фирма IBM рассматривает DB2 как дополнение, а не замену IMS, и в связи с которой эти два продукта разрабатывались таким образом, чтобы они могли работать совместно, как указывалось в предыдущих главах.
ПРОСТАЯ ВЫБОРКА
Выдать номера для всех поставляемых деталей:
SELECT НОМЕР_ДЕТАЛИ
FROM SP;
Имеем результат:
|
НОМЕР_ДЕТАЛИ
|
Р1
Р2
РЗ
Р4
Р5
Р6
Р1
Р2
Р2
Р2
Р4
Р5
Обратим внимание на дубликаты номеров деталей в этом результате. Система DB2 не исключает дубликатов из результата предложения SELECT, если пользователь явно не потребует это сделать с помощью ключевого слова DISTINCT (различный, различные), как показано в следующем примере.
ПРОСТАЯ ВЫБОРКА «SELECT*»
Выдать полные характеристики для всех поставщиков:
SELECT *
FROM S;
Результатом служит копия полной таблицы S.
Здесь звезда или звездочка служит кратким обозначением списка всех имен полей в таблице (таблицах), указанной(ых) во фразе FROM (из) в том порядке, в котором эти поля определяются в соответствующем (их) предложении(ях) CREATE TABLE. Таким образом, записанное выше предложение SELECT эквивалентно следующему:
SELECT НОМЕР_ПОСТАВЩИКА, ФАМИЛИЯ, СОСТОЯНИЕ, ГОРОД
FROM S;
Обозначение в виде звездочки удобно для интерактивных запросов, поскольку оно уменьшает число ударов по клавишам. Однако, оно таит потенциальную опасность при использовании во встроенном SQL (т. е. в предложениях SQL в прикладной программе), поскольку смысл знака «*» может измениться, если для этой программы перегенерируется план прикладной задачи, а в данном промежутке времени к рассматриваемой таблице был добавлен другой столбец. В этой книге «SELECT *» будет использоваться только в таких контекстах, где так делать безопасно (в основном только в интерактивных контекстах), и фактическим пользователям DB2 рекомендуется поступать подобным образом.
Отметим, наконец, что «*» может уточняться именем соответствующей таблицы. Допустима, например, следующая форма
SELECT S.*
FROM S;
ПРОСТОЕ ЭКВИСОЕДИНЕНИЕ
Выдать все комбинации информации о таких поставщиках и деталях, которые размещены в одном и том же городе (иначе говоря, «соразмещены» — безобразный, но удобный термин):
SELECT S.*, Р.*
FROM S, P
WHERE S.ГОРОД = Р.ГОРОД;
Заметим, что здесь ссылки на поля во фразе WHERE должны уточняться именами содержащих их таблиц. В результате получим следующую ниже таблицу 1. (Во избежание двусмысленности в этой таблице два столбца ГОРОД показаны явным образом как S.ГОРОД и Р.ГОРОД.)
Таблица 1
|
НОМЕР_ПОСТАВЩИКА
|
ФАМИЛИЯ
|
СОСТОЯНИЕ
|
S.ГОРОД
|
S1
S1
S1
S2
S2
S3
S3
S4
S4
S4
|
Смит
Смит
Смит
Джонс
Джонс
Блейк
Блейк
Кларк
Кларк
Кларк
|
20
20
20
10
10
30
30
20
20
20
|
Лондон
Лондон
Лондон
Париж
Париж
Париж
Париж
Лондон
Лондон
Лондон
Продолжение табл. 1
|
НОМЕР_ДЕТАЛИ
|
НАЗВАНИЕ
|
ЦВЕТ
|
ВЕС
|
Р.ГОРОД
|
Р1
Р4
Р6
Р2
Р5
Р2
Р5
Р1
Р4
Р6
|
Гайка
Винт
Блюм
Болт
Кулачок
Болт
Кулачок
Гайка
Винт
Блюм
|
Красный
Красный
Красный
Зеленый
Голубой
Зеленый
Голубой
Красный
Красный
Красный
|
12
14
19
17
12
17
12
12
14
19
|
Лондон
Лондон
Лондон
Париж
Париж
Париж
Париж
Лондон
Лондон
Лондон
Пояснение. Из формулировки задачи на естественном языке ясно, что требуемые данные можно получить из двух таблиц — S и Р. Поэтому в формулировке запроса на языке SQL мы прежде всего указываем эти две таблицы во фразе FROM, а затем выражаем во фразе WHERE соединение между ними, т. е. тот факт, что значения ГОРОД должны быть равны. Для того чтобы понять, как это делается, представим себе две строки, по одной из каждой таблицы, например строки, показанные ниже:
|
НОМЕР_ПОСТАВЩИКА
|
ФАМИЛИЯ
|
СОСТОЯНИЕ
|
S. ГОРОД
|
равны
|
S1
|
Смит
|
20
|
Лондон
|
НОМЕР_ДЕТАЛИ
|
НАЗВАНИЕ
|
ЦВЕТ
|
ВЕС
|
P. ГОРОД
|
Р1
|
Гайка
|
Красный
|
12
|
Лондон
Из этих двух строк можно видеть, что поставщик S1 и деталь Р1 в действительности «соразмещены». Из таких двух строк будет сформирована строка результата:
|
НОМЕР_ПОСТАВЩИКА
|
ФАМИЛИЯ
|
СОСТОЯНИЕ
|
S. ГОРОД
|
S1
|
Смит
|
20
|
Лондон
|
НОМЕР_ДЕТАЛИ
|
НАЗВАНИЕ
|
ЦВЕТ
|
ВЕС
|
P. ГОРОД
|
Р1
|
Гайка
|
Красный
|
12
|
Лондон
поскольку они удовлетворяют предикату во фразе WHERE (S.ГОРОД = Р.ГОРОД). Это имеет место и для всех других пар строк, содержащих соответствующие значения ГОРОД. Обратите внимание на то, что поставщик S5, размещающийся в Атенсе, не попадает в результирующую таблицу, так как нет каких-либо деталей, хранимых в этом городе. Подобным же образом результат не содержит детали РЗ, хранимой в Риме, ввиду того, что нет поставщиков, размещенных в Риме.
Результат данного запроса называется соединением таблиц S и Р по соответствию значений ГОРОД. Термин «соединение» используется также для обозначения операции конструирования такого результата. Условие S.ГОРОД = Р.ГОРОД называется условием соединения или предикатом соединения. В связи с приведенным примером нужно отметить ряд моментов. Одни из них имеют важное значение, другие не настолько существенны.
— Оба поля в предикате соединения должны быть либо числовыми, либо строками литер. Не обязательно, чтобы их типы данных были идентичны. Однако, по соображениям производительности, это было бы, вообще говоря, неплохо.
— Необязательно, чтобы поля в предикате соединения имели одинаковые имена, хотя очень часто это будет именно так.
— Нет необходимости в том, чтобы оператор сравнения в предикате соединения обязательно был равенством, хотя это будет очень часто. В дальнейшем будут приведены примеры такого рода (пример 4.3.2 и последняя часть примера 4.3.6). В случае оператора равенства соединение называют иногда эквисоединением.
— Фраза WHERE в SELECT-соединении может включать, помимо самого предиката соединения, другие условия. Эта возможность иллюстрируется ниже в примере 4.3.3.
— Можно, конечно, предусмотреть в SELECT выборку только специфицированных полей соединения, а не их всех. Эта возможность иллюстрируется ниже в примерах 4.3.4—4.3.6.
— Выражение
SELECT S.*,P.*
FROM S, P
. . . . . . ;
может быть еще более упрощено:
SELECT *
FROM S,P
. . . . . . ;
С другой стороны, оно может быть записано и в расширенном виде:
SELECT НОМЕР_ПОСТАВЩИКА, ФАМИЛИЯ, СОСТОЯНИЕ, S.город
НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ЦВЕТ, ВЕС, Р. ГОРОД
FROM S, P
. . . . . . ;
В такой формулировке для S.ГОРОД и Р.ГОРОД во фразе SELECT следует указывать их уточненные имена, как показано в примере, поскольку неуточненное имя ГОРОД было бы двусмысленным. Если Вам нужно освежить в памяти вопросы, касающиеся уточненных имен полей, см. введение к разделу 4.2.
— По определению, эквисоединение должно продуцировать результат, содержащий два идентичных столбца. Если исключить один из этих столбцов, то оставшееся называется естественным соединением. Для того, чтобы построить естественное соединение таблиц S и Р по городам в SQL, следовало бы записать:
SELECT НОМЕР_ПОСТАВЩИКА, ФАМИЛИЯ, СОСТОЯНИЕ, S.ГОРОД,
НОМЕР_ДЕТАЛИ, НАЗВАНИЕ, ЦВЕТ, ВЕС
FROM S, P
WHERE S.ГОРОД = Р.ГОРОД;
Естественное соединение является, вероятно, одной из наиболее полезных форм соединения — в такой степени, что мы часто используем неуточненный термин «соединение» специально для обозначения этого случая.
— Можно образовывать соединения также и трех, четырех, ... или любого числа таблиц. В примере 4.3.5, приведенном ниже, показано соединение трех таблиц.
Таблица 2
|
НОМЕР_ПОСТАВЩИКА
|
ФАМИЛИЯ
|
СОСТОЯНИЕ
|
S.ГОРОД
|
S1
S1
S1
S1
S1
S1
S2
.
.
.
S5
|
Смит
Смит
Смит
Смит
Смит
Смит
Джонс
.
.
.
Адамc
|
20
20
20
20
20
20
10
.
.
.
30
|
Лондон
Лондон
Лондон
Лондон
Лондон
Лондон
Париж
.
.
.
Атенс
Продолжение табл. 2
|
НОМЕР_ДЕТАЛИ
|
НАЗВАНИЕ
|
ЦВЕТ
|
ВЕС
|
Р.ГОРОД
|
Р1
Р2
РЗ
Р4
Р5
Р6
Р1
.
.
.
Р6
|
Гайка
Болт
Винт
Винт
Кулачок
Блюм
Гайка
.
.
Блюм
|
Красный
Зеленый
Голубой
Красный
Голубой
Красный
Красный
.
.
.
Красный
|
12
17
17
14
12
19
12
.
.
.
19
|
Лондон
Париж
Рим
Лондон
Париж
Лондон
Лондон
.
.
.
Лондон
— В табл. 2 рассматривается альтернативный ( и полезный) способ, позволяющий представить себе, каким образом концептуально могут конструироваться соединения. Прежде всего построим декартово произведение таблиц, перечисленных во фразе FROM. Декартово произведение множества, состоящего из n таблиц,— это таблица, содержащая всевозможные строки r, такие, что r является конкатенацией какой-либо строки из первой таблицы, строки из второй таблицы, ... и строки из n-й таблицы. Например, табл. 2 (назовем ее СР) представляет собой декартовым произведением таблиц S и Р (в указанном порядке). Полная таблица СР содержит 5х6=30 строк. Теперь исключим из этого декартова произведения все такие строки, которые не удовлетворяют предикату соединения. То, что останется, является требуемым соединением В рассматриваемом случае мы исключаем из таблицы СР все те строки, в которых S.ГОРОД не равен Р.ГОРОД. В результате получим в точности приведенное выше соединение. Между прочим, вполне возможно, хотя, может быть, и несколько необычным образом, сформулировать в языке SQL запрос, результатом которого будет декартово произведение. Например:
SELECT S S.*, P.*
FROM S, Р;
Результат. Упомянутая выше таблица СР.
ПРОСТОЙ ПОДЗАПРОС
Выдать фамилии поставщиков, которые поставляют деталь Р2.
SELECT ФАМИЛИЯ
FROM S
WHERE НОМЕР_ПОСТАВЩИКА IN
(SELECT НОМЕР_ПОСТАВЩИКА
FROM SP
WHERE НОМЕР_ДЕТАЛИ = 'P2');
Результат:
ФАМИЛИЯ
Смит
Джонс
Блейк
Кларк
Пояснение. При обработке полного запроса система обрабатывает прежде всего вложенный подзапрос. Этот подзапрос возвращает множество номеров поставщиков, которые поставляют деталь P2, а именно множество ('S1', 'S2', 'S3', 'S4'). Поэтому первоначальный запрос эквивалентен следующему простому запросу:
SELECT ФАМИЛИЯ FROM S
WHERE НОМЕР_ПОСТАВЩИКА IN ('S1'.'S2','S3','S4');
и, следовательно, получаем приведенный ранее результат.
Неявное уточнение фамилии в этом примере требует дополнительного обсуждения. Заметим, в частности, что «НОМЕР-ПОСТАВЩИКА» слева от IN неявным образом уточняется именем таблицы S, в то время как «НОМЕР-ПОСТАВЩИКА» в подзапросе неявно уточняется именем таблицы SP. Справедливо следующее общее правило: предполагается, что неуточненное имя поля должно уточняться именем таблицы (или псевдонимом таблицы — см. примеры 5.2.3–5.2.5 ниже), указанным в той фразе FROM, которая является непосредственной частью того же самого запроса или подзапроса. В случае поля НОМЕР-ПОСТАВЩИКА слева от IN этой фразой является «FROM S», а в случае поля НОМЕР-ПОСТАВЩИКА в подзапросе—это фраза «FROM SP». Для большей ясности повторим первоначальный запрос с явно указанными предполагаемыми уточнениями:
SELECT S. ФАМИЛИЯ
FROM S
WHERE S. НОМЕР_ПОСТАВЩИКА IN
(SELECT SP. НОМЕР_ПОСТАВЩИКА
FROM SP
WHERE SP. НОМЕР_ДЕТАЛИ = 'P2');
Неявные уточнения всегда можно отвергнуть путем задания явных уточнений. Это демонстрируется ниже в примерах 5.2.3–5.2.5.
Прежде чем перейти к нашему следующему примеру подзапроса, необходимо отметить еще один важный момент. Первоначальная задача — «Выдать фамилии поставщиков, которые поставляют деталь P2» — может быть эквивалентным образом выражена как запрос с использованием соединения:
SELECT S. ФАМИЛИЯ
FROM S, SP
WHERE S. НОМЕР_ПОСТАВЩИКА = SP. НОМЕР_ПОСТАВЩИКА
AND SP. НОМЕР_ДЕТАЛИ = 'P2';
Пояснение.
Соединение S и SP по номерам поставщиков представляет собой таблицу из 12 строк (по одной строке для каждой строки SP), каждая из которых состоит из соответствующей строки SP, дополненной значениями ФАМИЛИЯ, СОСТОЯНИЕ и ГОРОД для поставщика, указываемого значением НОМЕР-ПОСТАВЩИКА в этой строке. Из этих 12 строк только четыре относятся к детали P2. Окончательный результат получается, таким образом, выделением значения ФАМИЛИЯ из этих четырех строк.
Обе формулировки первоначального запроса, одна из которых использует подзапрос, а другая — соединение, в равной степени корректны. Вопрос о том, какой из этих формулировок отдать предпочтение,— исключительно дело вкуса данного пользователя.
Этим разделом завершается данная вводная
Этим разделом завершается данная вводная глава. В ней был приведен краткий обзор DB2, реляционной системы управления базами данных фирмы IBM для операционной системы MVS. Было пояснено в общих чертах, что такое реляционная система. Рассмотрена реляционная (табличная) структура данных и описаны некоторые из имеющихся в SQL операторов для работы с данными в такой табличной форме. В частности, мы коснулись вопроса о трех категориях предложений SQL (определение данных, манипулирование данными и управление данными) и привели примеры из первых двух категорий. Напоминаем читателю, что:
а) все предложения SQL являются выполняемыми; б) каждое предложение SQL, которое может быть введено с терминала, может быть также встроено в программу на языке ПЛ/1, КОБОЛ, ФОРТРАН или на языке ассемблера; в) предложения манипулирования данными SQL (SELECT, UPDATE и т. д.) оперируют над множествами. Наконец, были рассмотрены также различные варианты операционной обстановки., в которых может исполняться прикладная задача системы DB2, а именно: IMS, CICS и TSO. В следующей главе мы познакомимся с внутренней структурой и с основными компонентами DB2.
С.ЗСКАЛЯРНЫЕ ВЫРАЖЕНИЯ
скалярное — выражение
. : : скалярный—терм [арифметический—оператор скалярное — выражение]
скалярный — терм : : = [+ | –] скалярное — значение
скалярное — значение : : = имя — столбца
| ссылка — на — функцию | константа | USER
| (скалярное — выражение)
ссылка — на — функцию : : = COUNT (*)
| имя — функции (скалярное — выражение)
| имя — функции (DISTINCT имя — столбца)
имя — функции : : = COUNT | SUM|AVG | MAX | MIN
арифметический — оператор : : = + | – |*|/
СИМЕНА
имя — таблицы : : =
имя — базовой — таблицы
| имя — представления | псевдоним ) синоним
имя — базовой — таблицы : : = [имя — пользователя.] идентификатор
имя — пользователя : : = идентификатор
имя — представления : : = [имя — пользователя.] идентификатор
псевдоним : : = идентификатор
синоним : : = идентификатор
имя—столбца : := [имя—таблицы.] идентификатор
СИНОНИМЫ
Удобно завершить эту главу кратким обсуждением вопроса о синонимах, хотя он, в действительности, и не имеет отношения к каталогу как таковому, за исключением того, что синонимы записываются в каталог, как и многие другие объекты. Если говорить кратко, синоним представляет собой альтернативное имя таблицы — базовой таблицы или представления. В частности, можно определить синоним для таблицы, которая была создана каким-либо другим пользователем и для которой Вы должны были бы в противном случае использовать полностью уточненное имя. Например, пользователь АЛЬФА издает предложение:
CREATE TABLE ПРИМЕР. . .;
Пользователь БЕТА может обращаться к этой таблице, указывая АЛЬФА.ПРИМЕР:
SELECT *
FROM АЛЬФА.ПРИМЕР;
С другой стороны, пользователь БЕТА может издать предложение CREATE SYNONYM IJK FOR АЛЬФА.ПРИМЕР;
и может теперь обращаться к этой таблице, указывая просто IJK, например:
SELECT *
FROM IJK,
Имя IJK является совершенно приватным и локальным для пользователя БЕТА. Другой пользователь ГАММА также может иметь приватное и локальное имя IJK, отличное от имени, введенного пользователем БЕТА.
Другой пример:
CREATE SYNONYM ТАБЛИЦЫ FOR SYSIBM.SYSTABLES;
Имеется также предложение DROP SYNONYM (уничтожить синоним). Его синтаксис:
DROP SYNONYM синоним;
Например:
DROP SYNONYM ТАБЛИЦЫ;
СЛУЧАЙ ИСПОЛЬЗОВАНИЯ ОДНОЙ И ТОЙ ЖЕ ТАБЛИЦЫ В ПОДЗАПРОСЕ И ВНЕШНЕМ ЗАПРОСЕ
Выдать номера поставщиков, которые поставляют по крайней мере одну деталь, поставляемую поставщиком S2.
SELECT DISTINCT НОМЕР_ПОСТАВЩИКА
FROM SP
WHERE НОМЕР_ДЕТАЛИ IN
(SELECT НОМЕР_ДЕТАЛИ
FROM SP
WHERE НОМЕР_ПОСТАВЩИКА = 'S2');
Результат:
|
НОМЕР_ПОСТАВЩИКА
|
S1
S2
S3
S4
Отметим здесь, что ссылка на SP в подзапросе означает не то же самое, что ссылка на SP во внешнем запросе. В действительности, два имени SP обозначают различные переменные. Чтобы этот факт стал явным, можно использовать псевдонимы:
SELECT DISTINCT SPX. НОМЕР_ПОСТАВЩИКА
FROM SP SPX
WHERE SPX. НОМЕР_ДЕТАЛИ IN
(SELECT SPY. НОМЕР_ДЕТАЛИ
FROM SP SPY
WHERE SPY. НОМЕР_ПОСТАВЩИКА ='S2');
Эквивалентный запрос с использованием соединения имеет вид;
SELECT DISTINCT SPX. НОМЕР_ПОСТАВЩИКА
FROM SP SPX, SP SPY
WHERE SPX. НОМЕР_ДЕТАЛИ = SPY. НОМЕР_ДЕТАЛИ
AND SPY. НОМЕР_ ПОСТАВЩИКА = 'S2';
СЛУЧАЙ, КОГДА В КОРРЕЛИРОВАННОМ И ВНЕШНЕМ ЗАПРОСЕ ИСПОЛЬЗУЕТСЯ ОДНА И ТА ЖЕ ТАБЛИЦА
Выдать номера всех деталей, поставляемых более чем одним поставщиком. (Другое решение этой задачи дается позднее в примере 5.4.9):
SELECT DISTINCT SPX. НОМЕР_ДЕТАЛИ
FROM SP SPX
WHERE SPX. НОМЕР_ДЕТАЛИ IN
(SELECT SPY. НОМЕР_ДЕТАЛИ
FROM SP SPY
WHERE SPY. НОМЕР_ПОСТАВЩИКА
Ø
= SPX. НОМЕР_ПОСТАВЩИКА);
Результат:
|
НОМЕР_ДЕТАЛИ
|
P1
P2
P4
P5
Действие этого запроса можно пояснить следующим образом. «Поочередно для каждой строки таблицы SP, скажем SPX, выделить значение НОМЕР_ДЕТАЛИ, если и только если это значение входит в некоторую строку, скажем SPY, таблицы SP, значение столбца НОМЕР_ПОСТАВЩИКА в которой не является его значением в строке SPX». Заметим, что в этой формулировке должен
быть использован по крайней мере один псевдоним — либо SPX, либо SPY, но не они оба, может быть заменен просто на SP.
СОЕДИНЕНИЕ ПО УСЛОВИЮ «БОЛЬШЕ ЧЕМ»
Выдать все комбинации информации о поставщиках и деталях, таких, что город местонахождения поставщика следует за городом, где хранится деталь, в алфавитном порядке:
SELECT S.*, P.*
FROM S.P
WHERE S.ГOPOД > Р.ГОРОД;
Получим в результате следующую таблицу 3.
Таблица 3
|
НОМЕР_ПОСТАВЩИКА
|
ФАМИЛИЯ
|
СОСТОЯНИЕ
|
S.ГОРОД
|
S2
S2
S2
S3
S3
S3
|
Джонс
Джонс
Джонс
Блейк
Блейк
Блейк
|
10
10
10
30
30
30
|
Париж
Париж
Париж
Париж
Париж
Париж
Продолжение табл. 3
|
НОМЕР_ДЕТАЛИ
|
НАЗВАНИЕ
|
ЦВЕТ
|
ВЕС
|
Р.ГОРОД
|
P1
Р4
Р6
Р1
Р4
Р6
|
Гайка
Винт
Блюм
Гайка
Винт
Блюм
|
Красный Красный Красный Красный Красный Красный
|
12
14
19
12
14
19
|
Лондон
Лондон
Лондон
Лондон
Лондон
Лондон
СОЕДИНЕНИЕ С ДОПОЛНИТЕЛЬНЫМ УСЛОВИЕМ
Выдать все комбинации информации о поставщиках и информации о деталях, такие, что рассматриваемые поставщики и детали «соразмещены». Опустить при этом поставщиков с состоянием, равным 20:
SELECT S.*, Р.*
FROM S,P
WHERE S.ГОРОД = Р.ГОРОД
AND S.СОСТОЯНИЕ = 20;
Результат представлен в таблице 4.
Таблица 4
|
НОМЕР_ПОСТАВЩИКА
|
ФАМИЛИЯ
|
СОСТОЯНИЕ
|
S.ГОРОД
|
S2
S2
S3
S3
|
Джонс
Джонс
Блейк
Блейк
|
10
10
30
30
|
Париж
Париж
Париж
Париж
Продолжение табл. 4
|
НОМЕР_ДЕТАЛИ
|
НАЗВАНИЕ
|
ЦВЕТ
|
ВЕС
|
Р.ГОРОД
|
P2
Р5
Р2
Р5
|
Болт
Кулачок
Болт
Кулачок
|
Зеленый
Голубой
Зеленый
Голубой
|
17
12
17
12
|
Париж
Париж
Париж
Париж
СОЕДИНЕНИЕ ТАБЛИЦЫ С НЕЙ САМОЙ
Выдать все пары номеров поставщиков, такие, что образующие их поставщики соразмещены.
SELECT ПЕРВАЯ НОМЕР_ПОСТАВЩИКА,
ВТОРАЯ. НОМЕР_ПОСТАВЩИКА
FROM S ПЕРВАЯ, S ВТОРАЯ
WHERE ПЕРВАЯ.ГОРОД = ВТОРАЯ.ГОРОД;
Нетрудно видеть, что в этом запросе требуется соединение таблицы S с ней самой по соответствию городов. Поэтому таблица S дважды указывается во фразе FROM. Для того чтобы различать эти два ее вхождения, мы вводим в этой фразе два произвольных ее псевдонима, ПЕРВАЯ и ВТОРАЯ, и используем их как явные уточнители во фразах SELECT и WHERE. Получаем результат:
|
НОМЕР_ПОСТАВЩИКА
|
НОМЕР_ПОСТАВЩИКА
|
S1
S1
S2
S2
S3
S3
S4
S4
S5
|
S1
S4
S2
S3
S2
S3
S1
S4
S5
Мы можем привести в порядок этот результат, расширив следующим образом фразу WHERE:
SELECT ПЕРВАЯ.НОМЕР_ПОСТАВЩИКА.ВТОРАЯ.НОМЕР_ПОСТАВЩИКА
FROM S ПЕРВАЯ, S ВТОРАЯ
WHERE ПЕРВАЯ.ГОРОД = ВТОРАЯ.ГОРОД
AND ПЕРВАЯ.НОМЕР_ПОСТАВЩИКА < ВТОРАЯ. НОМЕР_ПОСТАВЩИКА
Условие ПЕРВАЯ.НОМЕР_ПОСТАВЩИКА < ВТОРАЯ.НОМЕР_ПОСТАВЩИКА дает двоякий эффект: а) оно исключает пары номеров поставщиков вида (х,х); б) оно гарантирует, что не будут появляться одновременно пары (х, у)
и (у, х).
Имеем в результате:
|
НОМЕР_ПОСТАВЩИКА
|
НОМЕР_ПОСТАВЩИКА
|
S1
S2
|
S4
S3
Это первый пример, в котором мы видели, что использование синонимов необходимо. Однако введение таких синонимов никогда не будет ошибкой, даже если их использование не необходимо, и иногда они могут помочь в том, чтобы данное предложение стало более ясным. Мы иногда будем использовать их в наших примерах в следующей главе.
Выдать все пары номеров поставщиков таких, что входящие к каждую пару поставщики соразмещены (пример 4.3.6);
|
S
|
НОМЕР_
ПОСТАВЩИКА
|
ГОРОД
|
|
S
|
НОМЕР_
ПОСТАВЩИКА
|
ГОРОД
|
|
|
|
|
|
_SX
|
_сZ
|
|
|
_SY
|
_сZ
|
|
P.
|
_SX
|
_SY
Для того чтобы специфицировать дополнительное условие SX<SY, если это необходимо, может быть использован блок условия. Обсуждение этого вопроса см. в главе 4.
СОЕДИНЕНИЕ ТРЕХ ТАБЛИЦ
Выдать все пары названий городов, таких, что какой-либо поставщик, находящийся в первом из этих городов, поставляет некоторую деталь, хранимую во втором городе. Например, поставщик Sl поставляет деталь Р1. Поставщик Sl находится в Лондоне, а деталь Р1 хранится также в Лондоне. Поэтому пара городов «Лондон, Лондон» — это пара городов, которая содержится в результате.
SELECT DISTINCT S.ГOPOД, Р.ГОРОД
FROM S, SP, P
WHERE S.HOMEP_ПОСТАВЩИКА = SP.HOMEP_ПОСТАВЩИКА
AND SP.HOMEP_ДЕТАЛИ = Р.НОМЕР_ДЕТАЛИ;
Получаем результат:
|
S.ГOPOД
|
Р.ГОРОД
|
Лондон
Лондон
Лондон
Париж
Париж
|
Лондон
Париж
Рим
Лондон
Париж
В качестве упражнения читателю следует установить, какие конкретно комбинации поставщик — деталь порождают каждую из строк результата в этом примере.
СПРЕДИКАТЫ
предикат
: : = условие
|условие AND предикат
|условие OR предикат
|NOT предикат
условие
: : = условие — сравнения
| условие — between
|условие — like
|условие — in
|условие — exists
условие — сравнения
: : = скалярное — выражение оператор — сравнения скалярное — выражение
|скалярное — выражение оператор — сравнения
(выражение — селекции — для — столбца)
[скалярное—выражение IS [NOT] NULL
оператор – сравнения
: : =+| ¬=| < | ¬ < | <= | > | ¬ > | > =
выражение — селекции — для — столбца
: : = фраза — селекции — для — столбца
фраза — from
[ фраза — where]
[фраза — группирования [фраза — having]]
фраза — селекции — для — столбца
: : = SELECT [DISTINCT] скалярное — выражение
условие — between
: : = имя — столбца [NOT] BETWEEN скалярное — выражение
AND скалярное — выражение условие — like
: : = имя — столбца
[NOT] LIKE скалярное — выражение
условие — in
: : = скалярное выражение [NOT] IN (множество — скаляров)
множество — скаляров
: : = список — константа
| выражение — селекции — для — столбца
условие — exists
: := EXISTS (выражение—селекции)