Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Тоу Д. -> "Настройка SQL. Для профессионалов" -> 110

Настройка SQL. Для профессионалов - Тоу Д.

Тоу Д. Настройка SQL. Для профессионалов — СПб.: Питер, 2004. — 333 c.
ISBN 5-94723-959-0
Скачать (прямая ссылка): nastroykasqldlyaprof2004.djvu
Предыдущая << 1 .. 104 105 106 107 108 109 < 110 > 111 112 113 114 115 116 .. 161 >> Следующая


ВНИМАНИЕ -----------------------------------------------------------------------------

Когда дело доходит до условий в разделе WHERE, базы данных интерпретируют значения null не интуитивным образом. Если вы считаете, что null по отношению к столбцу таблицы обозначает «неизвестно», а не «не применимо», то, возможно, сможете понять, Itait базы данных обрабатывают значения null в условиях. Кроме вопросов о том, равно ли значение в столбце null, практически любой вопрос, который вы можете задать о неизвестном значении, вернет ответ «неизвестно», что, на самом деле, и есть истинностное значение для большинства условий по null. С точки зрения отбрасывания строк для запроса, база данных обрабатывает истинностное значение «неизвестно» как FALSE, отбрасывая строки с неизвестными истинностными значениями во фразе WHERE. И, хотя NOT FALSE = TRUE, вы обнаружите, что NOT «неизвестно» = «неизвестно»!

Так как большинство фильтров для внешней таблицы отбрасывают внешние случаи внешних соединений, и предназначение внешних соединений состоит в сохранении таких случаев, вам необходимо обращать особое внимание на любые фильтры для внешних таблиц. Существует несколько сценариев, и вам следует потратить достаточно времени, чтобы определить, какой применим для конкретного случая.

¦ Фильтр достаточно редкий, например Некоторый_столбец IS NULL, и может вернуть значение TRUE для полей, равных null, принудительно вставленных во внешнем случае, и поэтому фильтр функционально верен.
224

7. Диаграммное изображение и настройка сложных SQL-запросов

¦ Разработчик не планировал отбрасывать внешнее соединение, и фильтрующее условие необходимо удалить.

¦ Фильтрующее условие предназначено для отбрасывания внешнего соединения, и соединение с таким же успехом может быть внутренним. В этом случае нет никакого функционального различия между запросом с соединением, выраженным как внешнее или внутреннее соединение. Однако, сделав его формально внутренним соединением, вы дадите базе данных больше степеней свободы для создания планов исполнения, которые могут выполнять соединение в любом направлении. Когда наилучший фильтр находится на той же стороне соединения, где и ранее присоединяемая внешне таблица, дополнительные степени свободы могут позволить выбрать лучший план исполнения. С другой стороны, превращение соединения во внутреннее может заставить оптимизатор сделать ошибку, которой он бы избежал с внешним соединением. Внешние соединения — это один из способов ограничения порядка соединения, когда вы сознательно хотите сделать это, даже если вам совсем не требуется сохранять внешний случай.

¦ Фильтрующее условие добавлено намеренно, но оно должно быть частью соединения! Если фильтрующее условие сделать частью соединения, то запрос к базе данных будет звучать как «Для каждой строки детальной таблицы найти подходящую строку из этой таблицы, удовлетворяющую фильтру, если таковая существует; иначе, поставить в соответствие псевдостроку, состоящую из значений null».

УСЛОВИЯ ВНЕШНЕГО СОЕДИНЕНИЯ ДЛЯ ОДНОЙ ТАБЛИЦЫ -----------------------------------------------

В старом стиле записи Oracle превращение фильтрующего условия в часть соединения производится за счет добавления (+). Например, двусоставное внешнее соединение с таблицей Code_Transl ati ons, которое использовалось в предыдущих примерах, выглядело бы так:

WHERE ...

AND 0.0rder_Type Code - OTypeTrans.Code(+)

AND OTypeTrans.Type(+) - 'ORDERJYPE'

В новом стиле записи соединений ANSI, единственном разрешенном в DB2 для записи внешних соединений, фильтрующее условие переходит в раздел FROM, чтобы стать явным условием соединения:

FROM ... Orders 0 ...

LEFT OUTER JOIN Code_Translations OTypeTrans

ON 0.0rder_Type_Code - OTypeTrans.Code AND CTypeTrans.Type - 'ORDER_TYPE'

В первоначальной записи внешних соединений в SQL Server база данных просто предполагает, что фильтрующее условие является частью соединения:

WHERE ...

AND 0.0rder_Type_Code *- OTypeTrans.Code AND OTypeTrans.Type = '0RDER_TYPE'

Обратите внимание, что это делает рассмотренную проблему невозможной для внешних соединений в SQL Server в старом стиле; база данных автоматически делает фильтр частью соединения. Также обратите внимание, что в редких случаях, когда фильтр действительно является фильтром, для получения желаемого результата вам необходимо либо преобразовать запись в новый стиль, либо превратить соединение в эквивалентный запрос NOT EXISTS1 о чем я расскажу позже.
Необычные диаграммы соединений

225

Рассмотрим первый сценарий подробнее. Возьмем запрос следующего вида:

SELECT ...

FROM Employees E

LEFT OUTER JOIN Departments D

ON E.Department_ID - D.DepartmentJO WHERE D.Dept_Manager_ID IS NULL

Что же на самом деле запрос хочет получить от базы данных? Семантически он запрашивает два различных набора строк. Один набор содержит данные обо всех сотрудниках, для которых не указан отдел, а второй отыскивает всех сотрудников, для которых указан отдел, не имеющий начальника. Существует вероятность, что приложение действительно хочет одновременно получить два таких разных набора, но более вероятно, что разработчик не заметил, что у такого простого запроса настолько сложный результат, и ему не нужен один из этих наборов строк.
Предыдущая << 1 .. 104 105 106 107 108 109 < 110 > 111 112 113 114 115 116 .. 161 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100