13-й час
Объединение таблиц в запросах

До сих пор создаваемые вами запросы извлекали данные из одной таблицы. Из этого урока вы узнаете, как связать таблицы в запросе так, чтобы можно было извлечь данные из нескольких таблиц.

Основными на этом уроке будут следующие темы.

• Основные подходы к связыванию таблиц
• Различные типы связей
• Как и когда следует использовать связывание таблиц
• Ряд практических примеров связывания таблиц
• Последствия неправильного связывания таблиц
• Использование псевдонимов таблиц в запросах

  Отбор данных из нескольких таблиц

Возможность отбора данных из нескольких таблиц является одной из самых полезных возможностей SQL Без такой возможности теряет смысл сама идея реляционной базы данных. Запросы к одной таблице могут быть весьма информативными, но в реальных базах данных чаще всего бывают нужны данные сразу из нескольких таблиц.

В ходе урока по нормализации вас пытались убедить в том, что база данных должна быть разделена на более мелкие и лучше поддающиеся управлению таблицы. После разделения таблиц на более мелкие у родственных таблиц оказываются общие столбцы — ключевые поля или просто ключи Такие ключи и используются для связывания родственных таблиц.

Связь объединяет две или несколько таблиц для того, чтобы обеспечить возможность извлечь данные сразу из нескольких таблиц.

Вы можете удивиться — зачем нормализовать таблицы, если в конце концов снова приходится объединять их, чтобы извлечь необходимые данные? Ответ прост: извлекать все данные из всех таблиц сразу приходится крайне редко, поэтому лучше объединять в запросе только те несколько таблиц, которые оказываются нужны в каждом конкретном случае. Хотя при этом работа базы данных может несколько замедлиться, это очевидно компенсируется существенным упрощением работы с базой данных и управления ею.

  Типы связывания

Несмотря на то, что число предлагаемых различными реализациями SQL способов связывания таблиц достаточно велико, мы рассмотрим только самые общие типы связывания, к которым относятся

• связывание по равенству (EQU JOINS):
• естественное связывание (NATURAL JOINS);
• связывание по неравенству (NON-FQUUOINS);
• внешнее связывание (OUTEP JCINS);
• рекурсивное связывание (SELF JOINS).

  Компоненты условия связывания

Как вы уже знаете из предыдущих уроков, ключевые слова SELECT и FROM являются необходимыми элементами оператора SQL, определяющего запрос. При связывании таблиц необходимым элементом оператора SQL является ключевое слово WHERE. Имена таблиц для связывания указываются в списке ключевого слова FROM. Связь определяется в выражении ключевого слова WHERE В выражении для связывания таблиц можно использовать операции =, <, >, <>, -.-, >-, '=, BETWEEN, LIKE и NOT. Но наиболее часто для связывания используется знак равенства

  Связывание по равенству

Связывание по равенству используется чаще всего и является, пожалуй, самым полезным типом связывания таблиц. Связывание по равенству называют также внутренним (INNER JOIN). При связывании по равенству таблицы связываются по общему столбцу, который в каждой из таблиц обычно является ключевым.

Синтаксис оператора, задающего связывание по равенству, должен быть следующим.

SELECT таблица1.столбец1, таблица2.столбец2... 

FROM таблица1, таблица2 [, таблицаЗ ] 

WHER3 таблица1.имя_столбца = таблица2.имя_столбца 

[ AND таблица1.имя_столбца таблицаЗ.имя столбца ]

Обратите внимание на отступы в приводимых ниже примерах операторов SQL. При правильном использовании отступов оператор понять легче. Использовать отступы не обязательно, но крайне желательно

Рассмотрим пример.

SELECT EMPLOYF,E_TBL.EMP_ID,

EMPLOYEE_PAY_TBL.DATE_HIRE FROM EMPLOYEEJTBL,

EMPLOYEE_PAY_TBL WHERE EKPLOYEE_TBL.EMP_ID = EMPLOYEE_PAY_TBL . EMP__ ID;

Этот оператор SQL возвращает табельный номер служащего и дату зачисления служащего в штат. Табельный номер извлекается из таблицы EMPLOYEE_TBL (хотя это поле имеется в обеих таблицах, все равно имя одной из таблиц необходимо указать), а дата зачисления в штат берется из таблицы EMPLOYEE__PAY_TBL. Ввиду того, что табельный номер служащего присутствует в обеих таблицах, имена соответствующих  двух столбцов таблиц рассматриваются как эквивалентные (что задается используемым в операторе равенством). Тем самым вы говорите серверу базы данных, откуда следует извлекать данные.

В следующем примере данные извлекаются из таблиц EMPLOYEEJTBL и EMPLOYEE_PAY_TBL, поскольку требуемые данные размещаются частично в одной, а частично в другой таблице. Здесь используется связывание по равенству.

SELECT EMPLOYEE_TBL.EMP_ID, EMPLOYEE_TBL.LAST_NAME,

EMPLOYEE_PAY_TBL.POSITION 

FROM EMPLOYEEJTBL, EMPLOYEE_PAY_TBL

WHEREEMPLOYEE_TBL.EMP_ID = EMPLOYEE_PAY_TBL.EMP_ID;

EMP_ID LAST_NAM POSITION

311549902 STEPHENS MARKETING

442346889 PLEW TEAM LEADER

213764555 GLASS SALES MANAGER

313782439 GLASS SALESMAN

220984332 WALLACE SHIPPER

443679012 SPURGEON SHIPPER

6 строк выбраны.

Обратите внимание на то, что в списке оператора SELECT вместе с именами каждого из столбцов указаны имена соответствующих таблиц. Это называется подробным определением столбцов в запросе. Подробные определения требуются только для тех столбцов, которые присутствуют в нескольких из указанных в запросе таблиц. Но в операторе обычно указываются подробные определения для всех столбцов, чтобы не возникало лишних вопросов при отладке или модификации программного кода SQL.

  Естественное связывание

Естественное связывание почти эквивалентно связыванию по равенству, но при естественном связывании таблиц повторения эквивалентных столбцов исключаются. Условие связывания оказывается таким же, но столбцы выбираются иначе.

Синтаксис соответствующего оператора следующий.

SELECT таблица1.*, таблица2.имя_столбца

[, таблицаЗ.имя_столбца ]

FROM таблица1, таблица2 [,таблицаЗ ] 

WHERE таблица1.имя_столбца = таблица2.имя_столбца 

[ AND таблица1.имя_столбца = таблицаЗ.имя~столбца ]

Например,

SELECT EMPLOYEEJTBL.*, EMPLOYEE_PAY_TBL.SALARY FROM EMPLOYEEJTBL,

EMPLOYEE_PAY_TBL WHERE EMPLOYEE_TBL.EMP_ID = EMPLOYEE_PAY_TBL.EMP_ID;

Этот оператор SQL возвращает данные всех столбцов из таблицы EMPLOYEE_TBL и значения SALARY из таблицы EMPLOYEE_PAY_TBL. Столбец EMP_ID имеется в обеих таблицах, но извлекается только из таблицы EMPLOYEE_TBL, поскольку во второй таблице соответствующий столбец содержит точно такую же информацию и поэтому извлекать ее нет смысла.

В следующем примере выбираются все столбцы из таблицы EMPLOYEE_TBL и один столбец из таблицы EMPLOYEE_PAY_TBL. He забывайте о том, что звездочка (*) представляет все столбцы таблицы

SELECT EMPLOYEE_TBL.*, EMPLOYEE_PAY_TBL.POSITION

FROM EMPLOYEEJTBL, EMPLOYEE_PAY_TBL

WHERE EMPLOYEE_TBL.EMP_ID = EMPLOYEE_PAY_TBL.EMP_ID;

EMP_ID LAST_NAM FIRST_NAM ADDRESS CITY ST ZIP PHONE PAGER POSITION

311549902 STEPHENS TINA D RR 3 BOX 17A GREENWOOD IN 47890

3178784465 MARKETING

442346889 PLEW LINDA С 3301 BEACON INDIANAPOLIS IN 46224

3172978990 TEAM LEADER

213764555 GLASS BRANDON S 1710 MAIN ST WHITELAND IN 47885

3178984321 3175709980 SALES MANAGER

313782439 GLASS JACOB 3789 RIVER BLVD INDIANAPOLIS IN 45734

3175457676 8887345678 SALESMAN

220984332 WALLACE MARIAH 7789 KEYSTONE INDIANAPOLIS IN 46741

3173325986 SHIPPER

443679012 SPURGEON TIFFANY 5 GEORGE COURT INDIANAPOLIS IN 46234

3175679007 SHIPPER

6 строк выбраны.

Обратите внимание на то, как здесь располагаются данные вывода Перенос строк возникает из-за того, что строки данных оказываются длиннее ширины страницы

  Использование псевдонимов для имен таблиц

Использование псевдонимов для имен таблиц означает переименование таблицы в рамках используемого оператора SQL. При этом истинное имя таблицы в базе данных не меняется. Как мы с вами увидим ниже, назначение таблице псевдонима необходимо при рекурсивном связывании (SELF JOIN). Часто псевдонимы назначаются таблицам с целью сокращения объема печатания, в результате чего операторы SQL становятся короче и проще для понимания. Кроме того, чем меньше печатать, тем меньше будет ошибок При назначении таблицам псевдонимов псевдонимы должны использоваться и при точном определении столбцов. Вот пример использования псевдонимов таблиц и соответствующее использование столбцов.

SELECT E.EMP_ID, EP.SALARY, EP.DATE_HIRE, E.LAST_NAME 

FROM EMPLOYEEJTBL E,

EMPLOYEE_PAY_TBL EP 

WHERE E.EMP_ID = EP.EMP_ID 

AND EP.SALARY > 20000;

В этом примере таблицам назначаются псевдонимы. Вместо имени EMPLOYEE_TBL используется Е, поскольку имя этой таблицы начинается с Е. Имя второй таблицы, EMPLOYEE_PAY_TBL, тоже начинается с Е, но для нее используется псевдоним ЕР, поскольку псевдонимы разных таблиц в одном операторе должны быть разными. Выбранные столбцы приравниваются с использованием псевдонимов таблиц. Обратите внимание на то, что для используемого в выражении ключевого слова WHERE имени столбца SALARY тоже должен использоваться псевдоним соответствующей таблицы.

  Связывание по неравенству

При связывании по неравенству (NON-EQUIJOINS) две или несколько таблиц объединяются по условию неравенства значения столбца таблицы значению из столбца другой таблицы.

Синтаксис соответствующей части оператора следующий.

FROM таблица1, таблица2 [,таблицаЗ ] 

WHERE таблица1.имя_столбца != таблица2.имя_столбца 

[ AND таблица1.имя_столбца != таблицаЗ.имя_столбца ]

Например,

SELECT EMPLOYEE_TBL.EMP_ID, EMPLOYEE_PAY TBL.DATE_HIRE 

FROM EMPLOYEE_TBL,

EMPLOYEE_PAY_TBL 

WHERE EMPLOYEE_TBL.EMP_ID != EMPLOYEE_PAY_TBL.EMP_ID;

Этот оператор SQL возвратит табельный номер служащего и даты поступления на работу для всех служащих с несоответствующими табельными номерами Вот пример связывания по неравенству из реальной базы данных

SELECT E.EMP_ID, E.LAST_HAME, P.POSITION 

FROM EMPLOYEE_TBL E,

EMPLOYEE_PAY_TBL P 

WHERE E.EMP_ID = P.EMP_ID;

EMP_ID LAST_NAM POSITION

442346889 PLEW MARKETING

213764555 GLASS MARKETING

313782439 GLASS MARKETING

220984332 WALLACE MARKETING

443679012 SPURGEON MARKETING

311549902 STEPHENS TEAM LEADER

213764555 GLASS TEAM LEADER

313782439 GLASS TEAM LEADER

220984332 WALLACE TEAM LEADER

443679012 SPURGEON TEAM LEADER

311549902 STEPHENS SALES MANAGER

442346889 PLEW SALES MANAGER

313782439 GLASS SALES MANAGER

220984332 WALLACE SALES MANAGER

443679012 SPURGEON SALES MANAGER

3115499C2 STEPHENS SALESMAN

442346889 PLEW SALESMAN

213764555 GLASS SALESMAN

220984332 WALLACE SALESMAN

443679012 SPURGEON SALESMAN

311549902 STEPHENS SHIPPER

442346889 PLEW SHIPPER

213764555 GLASS SHIPPER

313782439 GLASS SHIPPER

30 строк выбраны.

Вы, наверное, удивитесь, что в данном случае из базы данных были извлечены 30 строк данных, хотя в таблице имеется всего 6 записей Объяснение этому следующее. Каждой записи из таблицы EMPLOYEE_TBL соответствует запись из таблицы EMPLOYEE_PAY_TBL. Но по причине связывания по неравенству каждой записи из первой таблицы сопоставляются все записи второй таблицы, за исключением той самой единственной соответствующей записи Значит, каждая строка первой таблицы оказывается связанной с пятью строками второй. Записей всего 6, поэтому в результате мы получаем 30 строк.

В отличие от данного случая, в предыдущем разделе при связывании по равенству каждая строка таблицы связывалась с единственной соответствующей строкой второй таблицы, поэтому там в выводе получалось 6 строк.

При связывании по неравенству обычно в выводе присутствует ряд строк, которые на самом деле оказываются ненужными, так что результаты запроса, в котором используется связывание по неравенству, всегда требуют дополнительной проверки

  Внешнее связывание

Внешнее связывание (OUTER JOIN) используется, когда вывод должен содержать все записи одной таблицы, даже если некоторые из ее записей не имеют соответствующих записей в другой таблице. В запросе для задания внешнего связывания используется (+). Символ (+) помещается в конце имени таблицы в выражении ключевого слова WHERE. Таблицей с символами ( + ) должна быть та таблица, записям которой нет соответствующих записей из другой таблицы. Во многих реализациях языка внешнее связывание разбито на левое внешнее связывание (LEFT OUTER JOIN), правое внешнее связывание (RIGHT OUTER JOIN) и полное внешнее связывание (FULL OUTER JOIN). В таких реализациях внешнее связывание (OUTER JOIN) обычно является опцией.

Обязательно проверьте правила использования внешнего связывания и синтаксис соответствующих операторов по документации той реализации языка, с которой вы работаете Символы ( + ) используются в большинстве основных реализаций SQL, но стандартом они не задаются

Общий синтаксис следующий.

FROM таблица1

{RIGHT | LEFT | FULL} [OUTER] JOIN

ON таблица2

В Oracle используется следующий синтаксис.

FROM таблица1, таблица2 [,таблицаЗ ]

WHERE таблица1.имя_столбца[(+)] = таблица2.имя_столбца[(+)] 

[ AND таблица!.имя_столбца[(+)] = таблицаЗ.имя_столбца[(+)]]

Внешнее связывание можно задать только для,одной из связываемых сторон, но зато внешнее связывание можно указать для нескольких столбцов одной таблицы.

Использование внешнего связывания поясняется следующими примерами. В первом примере выбираются описание товара и его количество, причем эти значения извлекаются из двух разных таблиц. Здесь нужно помнить о том, что не для каждого товара имеется соответствующая запись в таблице ORDERS_TBL. Сначала используем связывание по равенству:

SELECT P.PROD_DESC, О. QTY 

FROM PRODUCTS_TBL P,

ORDERS_TBL О 

WHERE P.PROD_ID = O.PROD_ID;

PRODJ3ESC QTY

КОСТЮМ ВЕДЬМЫ 1

ПЛАСТИКОВЫЕ ТЫКВЫ 25

ПЛАСТИКОВЫЕ ТЫКВЫ 2

ФОНАРИ 10

ИСКУССТВЕННЫЕ ПАРАФИНОВЫЕ ЗУБЫ 20

ЦЕПОЧКА ДЛЯ КЛЮЧЕЙ 1

6 строк выбраны.

Здесь оказались выбранными всего 6 строк, хотя различных товаров более 10. Но вы хотели бы увидеть список всех товаров, независимо от того, имеются ли на них заказы или нет.

В следующем примере эта задача решается с помощью внешнего связывания. Для соответствующего оператора используется синтаксис Oracle.

SELECT P.PROD_DESC, О.QTY 

FROM PRODUCTS_TBL P,

ORDERS_TBL О 

WHERE P . PROD_ID = О . PROD_ID (+);

PROD_DESC QTY

КОСТЮМ ВЕДЬМЫ 1

МАСКИ В АССОРТИМЕНТЕ

ИСКУССТВЕННЫЕ ПАРАФИНОВЫЕ ЗУБЫ 20

КОСТЮМЫ В АССОРТИМЕНТЕ

ПЛАСТИКОВЫЕ ТЫКВЫ 25

ПЛАСТИКОВЫЕ ТЫКВЫ 2

ТЫКВЕННЫЕ КОНФЕТЫ

ПЛАСТИКОВЫЕ ПАУКИ

СЛАДКАЯ КУКУРУЗА

ФОНАРИ 10

ЦЕПОЧКА ДЛЯ КЛЮЧЕЙ 1

ПОЛОЧКА ИЗ ДУБА

12 строк выбраны.

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

 

  Рекурсивное связывание

Рекурсивное связывание (SELF JOIN) предполагает связывание таблицы с ней же самой, как будто бы это были две таблицы, применяя временное переименование таблицы в операторе SQL. Синтаксис такого оператора следующий.

SELECT А.имя_столбца, В.имя_столбца [, С.имя_столбца ] 

FROM таблица1 А, таблица2 В [, таблицаЗ С ] 

WHERE А.имя_столбца = В.имя_столбца 

[ AND А.имя_столбца = С.имя_столбца ]

Например,

SELECT A.LASTJJAME, B.LAST_NIME, A.FIRST_NAME 

FROM EMPLOYEE_TBL A,

 EMPLOYEEJTBL В 

WHERE A.LAST_NAME = B.LAST_NAME;

Этот оператор SQL возвратит имена всех служащих с одинаковыми фамилиями из таблицы EMPLOYEEJTBL. Рекурсивное связывание удобно использовать, когда все необходимые данные размещаются в одной таблице, но требуется каким-то образом сравнить одни записи таблицы с другими.

Часто использование рекурсивного связывания объясняется на следующем примере. Предположим, что имеется таблица, в которой хранятся табельный номер, имя служащего и табельный номер менеджера этого служащего, и предположим, что возникла необходимость получить список служащих вместе с именами их менеджеров. Проблема в том, что столбца с именами менеджеров в данной таблице нет — имеется только столбец с именами всех служащих.

SELECT FROM EMP;

ID NAME MNGR_ID

1 JOHN 0

2 MARY 1

3 STEVE 1

4 JACK 2

5 SUE 2

Поэтому в следующем запросе таблица EMP в выражении ключевого слова FROMвключена дважды и ей назначены два псевдонима. Имея два псевдонима, таблицу можно рассматривать как две разные таблицы. Все менеджеры являются также служащими, поэтому в условии связывания можно сравнить табельный номер служащего из "первой" таблицы с табельным номером менеджера из "второй" таблицы. Теперь "первая" таблица хранит информацию о служащих, а "вторая" — о менеджерах.

SELECT El.NAME, E2.NAME 

FROM EMP El, EMP E2 

WHERE E1.MGR_ID = E2.ID;

NAME NAME

MARY JOHN

STEVE JOHN

JACK MARY

SUE MARY

 

  Связывание по нескольким ключам

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

Рассмотрим для примера следующие таблицы.

  SQL> desc prod

Имя               NULL? Тип данных

SERIAL_NUMBER NOT NULL NUMBER(10)

VENDOR_NUMBER NOT NULL NUMBER(10)

PRODUCT_NAME NOT NULL VARCHAR2OO)

COST NOT NULL NITMBER (8,2)

SQL> desc prod NULL? Тип данных

ORD_NO NOT NULL NUMBER(10)

SERIAL_NUMBER NOT NULL NUMBER(10}

VENDOKJMUMBER NOT NULL NUMBER(10)

QUANTITY NOT NULL NUMBERt5)

ORD_DATE NOT NULL DATE

Ключом в таблице PROD является комбинация столбцов SERTAL_NUMBER и VENDOR_NUMBER Верояшо, в данной торговой компании некоторые товары имеют один серийный номер, но различаются по коду производителя

Внешним ключом в таблице ORD тоже является комбинация столбцов

SERIAL_NUMBER И VENDOR_NUMBER.

При выборе данных из обеих таблиц (PROD и ORD) оператор связывания может выглядеть следующим образом:

SELECT Р.PRODUCT_NAME, O.ORD_DATE, О.QUANTITY 

FROM PROD P, ORD О

WHERE P.SERIAL_NUMBER = 0.SER1AL_NUMBER 

AND P.VENDOR_NUMBER = О.VENDOR_NUMBER;

 

  Вопросы связывания

Прежде чем использовать связывание, следует получить ответы на ряд важных вопросов Например, какие из столбцов необходимо связать, имеются ли общие столбцы вообще, а также вопросы оптимизации Вопросы оптимизации будут рассматриваться в ходе урока 18, "Управление доступом к базе данных".

  Использование связующей таблицы

Как осуществить связывание? Если нужно связать таблицы, не имеющие общих столбцов, необходимо использовать третью таблицу, имеющую общие столбцы как с первой, так и со второй таблицей. Такая таблица называется связующей таблицей

Связующую таблицу можно использовать для связывания как таблиц с общими столбцами, так и таблиц, не имеющих общих столбцов.

Для примера использования связующей таблицы рассмотрим следующие три таблицы.

CUSTOMER_TBL

CUST_IDVARCHAR2(10)        NOT NULL  Ключевое поле

CUST_NAME VARCHAR2(30)    NOT NULL

CUST_ADDRESS VARCHAR2(20) NOT NULL

CUST_CITY VARCHAR2U5)     NOT NULL

CUST_STATE CHAR(2)        NOT NULL

CUST_ZIP NUMBER(5)        NOT NULL

CUST_PHONE NUMBER(10)

CUST_FAX NUMBER(10)

 

ORDERS_TBL

ORD_NUMVARCHAR2(10)        NOT NULL    Ключевое поле

CUST_ID VARCHAR2(10)       NOT NULL

PROD_ID VARCHAR2(10)       NOT NULL

QTY NUMBER(6)              NOT NULL

ORD_DATE DATE

 

PRODUCTS_TBL

PROD_ID VARCHAR2UO)         NOT NULL   Ключевое поле

PROD_DESC VARCHAR2(40)      NOT NULL

COST NUMBER (6,2)           NOT NULL

Необходимо использовать таблицы CUSTOMERJTBL и pfi ODUCTS_TBL. У этих таблиц нет общих столбцов, по которым можно было бы выполнить связывание. Приходится использовать таблицу ORDERS_TBL, в которой имеется поле CUST_ID, присутствующее и в таблице CUSTOMER_TBL, и в таблице PRODUCTS_TBL. Условия связывания и результаты выглядят следующим образом.

SELECT C.CUST_NAME, P.PROD_DESC FROM CUSTOMER_TBL С,

PRODUCTS_TBL P,

ORDERS_TBL О

WHERE C.CUST_ID = O.CUST_ID AND P.PROD_ID = O.PROD_ID;

CUST_NAME PROD_DESC

LESLIE GLEASON КОСТЮМ ВЕДЬМЫ

SCHYLERS NOVELTIES ПЛАСТИКОВЫЕ ТЫКВЫ

WENDY WOLF ПЛАСТИКОВЫЕ ТЫКВЫ

GAVINS PLACE ФОНАРИ

SCOTTYS MARKET ИСКУССТВЕННЫЕ ПАРАФИНОВЫЕ ЗУБЫ

ANDYS CANDIES ЦЕПОЧКА ДЛЯ КЛЮЧЕЙ

6 строк выбраны.

Обратите внимание на назначение таблицам псевдонимов и их использование в выражении ключевого слова WHERE.

 

  Декартово произведение

Декартово произведение является результатом декартова связывания (CARTESIAN JOIN) или отсутствия связывания таблиц в запросе. Если в запросе указываются две или более таблиц и не используется их связывание, то в выводе будут присутствовать все возможные комбинации строк выбранных таблиц. Если таблицы большие, в результате получится, может быть, сотни, тысячи или даже миллионы записей. При использовании в запросе декартова произведения таблиц настоятельно рекомендуется использовать ключевое слово WHERE. Декартово произведение таблиц иначе называется кросс-связыванием (cross join).

Синтаксис соответствующей части оператора следующий.

FROM таблица1, таблица2 [,таблицаЗ ] 

WHERE таблица1, таблица2 [,таблицаЗ ]

Вот пример кросс-связывания или ужасного декартова произведения таблиц.

SELECT E.EMP_ID, E.LAST_NAME, P.POSITION 

FROM EMPLOYEE_TBL E,

EMPLOYEE_PAY_TBL P;

EMP ID

LAST NAM

POSITION

311549902 442346889 213764555 313782439 220984332 443679012 311549902 442346889 213764555 313782439 220984332 443679012 311549902 442346889 213764555 313782439 220984332 443679012 311549902 442346889 213764555 313782439 220984332 443679012 311549902 442346889 213764555 313782439 220984332 443679012 311549902 442346889 213764555

STEPHENS PLEW GLASS GLASS WALLACE SPURGEON STEPHENS PLEW GLASS GLASS WALLACE SPURGEON STEPHENS PLEW GLASS GLASS WALLACE SPURGEON STEPHENS PLEW GLASS GLASS WALLACE SPURGEON STEPHENS PLEW GLASS GLASS WALLACE SPURGEON STEPHENS PLEW GLASS

MARKETING MARKETING MARKETING MARKETING MARKETING MARKETING TEAM LEADER TEAM LEADER TEAM LEADER TEAM LEADER TEAM LEADER TEAM LEADER SALES MANAGER SALES MANAGER SALES MANAGER SALES MANAGER SALES MANAGER SALES MANAGER SALESMAN SALESMAN SALESMAN SALESMAN SALESMAN SALESMAN SHIPPER SHIPPER SHIPPER SHIPPER SHIPPER SHIPPER SHIPPER SHIPPER SHIPPER

313782439 220984332 443679012

GLASS WALLACE SPORGEON

SHIPPER SHIPPER SHIPPER

36 строк выбраны.

Ввиду того, что никакого связывания не было задано, данные были выбраны из двух отдельных таблиц. Не было указано, как связывать записи одной таблицы с записями другой, и поэтому сервер базы данных связал каждую запись одной таблицы со всеми записями другой. В каждой из этих таблиц было по 6 записей, поэтому в результате их получилось 36.

Чтобы разобраться в том, что такое декартово произведение таблиц, рассмотрите следующие примеры.

SQL> SELECT X FROM TABLE1;

X

-

В 

С 

D

4 строки выбраны

SQL> SELECT X FROM TABLE2;

X

-

В 

С 

D

4 строки выбраны.

SQL> SELECT TABLE1.X, TABLE2.X 

2* FROM TABLE1, TABLE2;

 

X X

_  _

A A

В А

С А

D A

А В

в в 

с в

D В

А С

в с 

с с

D С

A D

В D

С D

D D

16 строк выбраны.

При связывании таблиц в запросе всегда следует быть внимательным. Если какие-то две таблицы в запросе окажутся не связанными и число записей в каждой из них будет около 1000, то их прямое произведение будет содержать уже 1000000 выводимых записей.

  Резюме

Вы получили представление об одной из важнейших возможностей SQL — связывании таблиц. Представьте, какие были бы ограничения, если бы в запросе нельзя было извлечь данные из нескольких таблиц сразу. Мы с вами рассмотрели несколько типов связывания таблиц, каждый из которых выполняет свои задачи в зависимости от условий запроса. Данные можно связывать по равенству или по неравенству. Внешнее связывание позволяет извлекать данные из связанных таблиц даже тогда, когда не все записи одной таблицы имеют соответствующие записи в другой. Рекурсивное связывание позволяет связать таблицу саму с собой. Берегитесь кросс-связывания, известного так же, как декартово произведение таблиц. В результате декартова произведения, возникающего при использовании в запросе нескольких таблиц без их связывания, объем выводимых данных может оказаться огромным. При выборе данных из нескольких таблиц внимательно проверьте условия связывания таблиц по родственным столбцам (обычно это должны быть ключевые поля). Неправильное связывание таблиц обычно оборачивается неправильно выведенными или неверными данными.

  Вопросы и ответы

При связывании таблиц должны ли они связываться в том же порядке, в каком они указаны в выражении ключевого слова FROM?

Нет, но не следует забывать, что от порядка перечисления таблиц в выражении ключевого слова FROM и от порядка, в котором связаны таблицы, может зависеть скорость выполнения запроса.

При использовании связующей таблицы для связывания пары таблиц, не имеющих общих столбцов, обязательно ли выбирать в запросе хотя бы один из ее столбцов?

Нет, использование в операторе запроса связующей таблицы не обязывает отображать данные ее столбцов.

Можно ли связывать в запросе не один, а несколько столбцов таблиц?

Да, чтобы обеспечить необходимое соответствие данных, вполне вероятно, что в запросе может понадобиться связывание нескольких столбцов таблиц.

  Практикум

Задания практических занятий разделены на тесты и упражнения. Тесты предназначены для проверки общего уровня понимания рассмотренного материала. Упражнения дают возможность применить на практике идеи, обсуждавшиеся в ходе текущего урока, в комбинации с идеями из предыдущих уроков. Мы рекомендуем ответить на тестовые вопросы и выполнить упражнения прежде, чем продолжать дальнейшее чтение книги. Ответы можно проверить по Приложению Б, "Ответы".

 

  Тесты

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

2. Какая часть оператора SQL задает условия связывания таблиц?

3. Какой тип связывания используется тогда, когда необходимо задать эквивалентность строк связываемых таблиц?

4. Что будет, если в запросе указать выборку из двух таблиц, но не связать их?

5. Рассмотрите следующие таблицы.

ORDERS_TBL

ORD_NUM VARCHAR2(10)    NOT NULL   Ключевое поле

CUST_ID VARCHAR2(10)    NOT NULL

PROD_ID VARCHAR2(10)    NOT NULL

QTY NUMBER(6)           NOT NULL

ORD_DATE DATE

PRODUCTS TBL

PROD_ID VARCHAR2CLO)   NOT NULL Ключевое поле

PROD_DESC VARCHAR2(40) NOT NULL

COST NUMBER (6,2)      NOT NULL

Правильно ли составлен следующий оператор, если предполагалось внешнее связывание этих таблиц?

SELECT C.CUST_ID, C.CUST_NAME, О.ORD_NUM 

FROM CUSTOMERJTBL С, ORDERS_TBL 0 

WHERE C.CUST_ID{+) = O.CUST_ID(+)

  Упражнения

Выполните упражнения для следующих таблиц.

 

EMPLOYEE TBL

EMP ID VARCHAR2(9)       NOT NULL Ключевое поле 

LAST NAME VARCHAR2(i5)   NOT NULL 

FIRST NAME VARCHAR2(15)  NOT NULL 

MIDDLE NAME VARCHAR2 ( 15 } 

ADDRESS VARCHAR2(30)     NOT NULL 

CITY VARCHAR2(15)        NOT NULL 

STATE CHAR (2)           NOT NULL 

ZIP NUMBER (5)           NOT NULL 

PHONE CHAR (10) 

PAGER CHAR (10)

 

EMPLOYEE PAY TBL

 

EMP ID VARCHAR2O)                     NOT NULL   Ключевое поле

POSITION VARCHAR2U5)                  NOT NULL 

DATE HIRE DATE PAY RATE NUMBER (4,2)   NOT NULL 

DATE LAST-RAISE DATE SALARY NUMBER (6,2) 

BONUS NUMBER (4,2)

CONSTRAINT EMP FK FOREIGN KEY (EMP ID) REFERENCED EMPLOYEE TBL (EMP ID)

 

CUSTOMERS TBL




CUST ID CUST NAME CUST ADDRESS CUST CITY

CUST STATE CUST ZIP CUST PHONE CUST_FAX

VARCHAR2 (10) VARCHAR2 (30) VARCHAR2 (20) VARCHAR2 (15) CHAR ( 2 ) NUMBER (5) NUMBER (10) NUMBER (10)

NOT NULL NOT NULL NOT NULL NOT NULL NOT NULL NOT NULL

Ключевое поле

ORDERS TBL




ORD NUM CUST ID PROD ID QTY ORD DATE

VARCHAR2 (10) VARCHAR2 (10) VARCHAR2(10) NUMBER (6) DATE

NOT NULL NOT NULL NOT NULL NOT NULL

Ключевое поле

PRODUCTS TBL




PROD ID PROD DESC COST

VARCHAR2 (10) VARCHAR2 (40) NUMBER (6, 2)

NOT NULL NOT NULL NOT NULL

Ключевое поле

1. Запишите оператор SQL, возвращающий EMP_ID, LAST_NAME и FIRST NAME из таблицы EMPLOYEE_TBL; SALARY и BONUS из таблицы EMPLOYEE_PAYJTBL.

2. Выберите из таблицы CUSTOMERS_TBL столбцы CUST_ID и CUST "NAME из таблицы PRODUCTS_TBL - столбцы PROD_ID и COST, а из таблицы ORDERS_TBL - ORD_NUM и QTY. Объедините три эти таблицы в одном оператопе SOL.