Самоучитель по SQL-сервер в Linux



Выбор источников в секции FROM

В секции FROM указывается источник данных — таблица или итоговый набор. Секция может содержать несколько источников, разделенных запятыми. Результат подобного перечисления функционально эквивалентен перекрестному объединению, о котором рассказано в подразделе «Объединение наборов данных».

Использование нескольких источников данных в PostgreSQL требует осторожности. В результате выполнения команды SELECT для нескольких источников без секций WHERE и JOIN, уточняющих связи между источниками, возвращается полное декартово произведение источников. Иначе говоря, итоговый набор содержит все возможные комбинации записей из всех источников.

Обычно для уточнения связей между источниками, перечисленными через запятую в секции FROM, используется секция WHERE. Пример приведен в листинге 4.27 (за дополнительной информацией о секции WHERE обращайтесь к подразделу «Уточнение запросов»).

Листинг 4.27. Выборка из нескольких таблиц

booktown=# SELECT books.id, title, authors_id, last_name

booktown-# FROM books, authors

booktown-# WHERE books.authored = authors.id;

id | title | id | last_name

190 | Little Women | 16 | Alcott

156 | The Tell-Tale Heart | 115 | Рое

41472 | Practical PostgreSQL | 1212 | Worsley

2038 | Dynamic Anatomy | 1644 | Hogarth

1608 | The Cat in the Hat | 1809 | Geisel

1590 |Bartholomew and the Oobleck | 1809 | Geisel

4513 | Dune | 1866 | Herbert

4267 | 2001: A Space Odyssey | 2001 | Clarke

1501 | Goodnight Moon | 2031 | Brown

7808 | The Shining | 4156 | King

41473 |Programming Python | 7805 | Lutz

41477 |Learning Python | 7805 | Lutz

41478 | Perl Cookbook | 7806 | Christiansen

25908 | Franklin in the Dark | 15990 | Bourgeois

1234 | The Velveteen Rabbit | 25041 | Bianco

(15 rows)

При использовании ссылок на имена полей, относящихся к разным источникам, может возникнуть неоднозначность. Предположим, команда SELECT получает исходные данные из таблиц books и authors. В каждой из этих таблиц имеется поле с именем id. Без дополнительных уточнений PostgreSQL не сможет определить, к какой таблице относится ссылка на поле i d в следующей команде:

booktown=# SELECT id FROM books, authors

ERROR: Column reference "id" is ambiguous

Для предотвращения неоднозначности в «полные» имена столбцов включается имя таблицы. При этом используется специальный синтаксис, называемый точечной записью (название связано с тем, что имя таблицы отделяется от имени поля точкой). Например, books .id означает поле id таблицы books.

Точечная запись обязательна только при наличии неоднозначности между наборами данных. Как показано в листинге 4.27, ссылка может состоять только из имени поля — при условии, что это имя уникально во всех наборах данных, перечисленных в секции FROM. В приведенном примере поле title присутствует только в таблице books, а поле last_name входит только в таблицу authors, поэтому на их имена можно ссылаться без уточнения.

Если в качестве источника используется итоговый набор, созданный подзапросом, то весь подзапрос заключается в круглые скобки. По наличию круглых скобок PostgreSQL узнает о том, что команда SELECT интерпретируется как подзапрос, и выполняет ее перед выполнением внешней команды SELECT.

В листинге 4.28 приведен несколько необычный запрос, который производит выборку значений всех полей (*) таблицы books с использованием подзапроса. Затем из полученного набора «выбирается» строковая константа test и значение поля id.

Листинг 4.28. Выборка из подзапроса

booktown=# SELECT 'test' AS test, id

booktown-# FROM (SELECT * FROM books)

booktown-# AS example_sub_query;

test | id

test | 7808

test | 4513

test | 4267

test | 1608

test | 1590

test | 25908

test | 1501

test | 190

test | 1234

test | 2038

test | 156

test | 41472

test | 41473

test | 41477

test | 41478

(15 rows)

Странность запроса в листинге 4.28 заключается в том, что общий результат принципиально не отличается от прямой выборки из таблицы books, поскольку результат подзапроса идентичен ее содержимому. Строковая константа из одной команды SELECT комбинируется с данными из набора, полученного другой командой SELECT. Более реалистичный пример использования подзапросов приведен ниже в разделе «Подзапросы», но сначала необходимо лучше разобраться в том, как работает команда SELECT.

ПРИМЕЧАНИЕ

Необязательное ключевое слово ONLY перед именем таблицы, которая является базовой по отношению к другим таблицам, означает, что выборка из производных таблиц не выполняется (наследование рассматривается в главе 7).

Синонимы источников данных в секции FROM

Источникам данных в секции FROM — таблицам, подзапросам и т. д. — можно назначать синонимы в секции AS (по аналогии с отдельными полями). Синонимы часто используются для упрощения точечной записи, о которой говорилось в преды-

дущем разделе. Наличие синонима для набора данных позволяет обращаться к нему при помощи точечной записи, что делает команды SQL более компактными и наглядными. В листинге 4.29 приведен запрос из листинга 4.27 с упрощением точечной записи при помощи секции AS.

Листинг 4.29. Определение синонимов для источников данных

booktown=# SELECT b.id, title, a.id, last_name

booktown-# FROM books AS b, authors AS a

booktown-# WHERE b.author_id = a.id;

id | title | id lastjname

190 | Little Women | 16 | Alcott

156 | The Tell-Tale Heart | 115 | Рое

41472 | Practical PostgreSQL | 1212 | Worsley

2038 | Dynamic Anatomy | 1644 | Hogarth

1608 | The Cat in the Hat | 1809 | Geisel

1590 | Bartholomew and the Oobleck | 1809 | Geisel

4513 | Dune | 1866 | Herbert

4267 | 2001: A Space Odyssey | 2001 | Clarke

1501 | Goodnight Moon | 2031 | Brown

7808 | The Shining | 4156 | King

41473 | Programming Python | 7805 | Lutz

41477 | Learning Python | 7805 | Lutz

41478 | Perl Cookbook | 7806 | Christiansen

25908 | Franklin in the Dark 15990 | Bourgeois

1234 | The Velveteen Rabbit | 25041 | Bianco

(15 rows)

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

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

ПРИМЕЧАНИЕ

Ключевое слово AS не является обязательным. Если оно отсутствует в команде, PostgreSQL считает, что все идентификаторы после ключевого слова FROM являются синонимами.

В листинге 4.30 приведен запрос из листинга 4.29, в котором полям id обеих таблиц назначаются уникальные идентификаторы, что позволяет ссылаться на них непосредственно (то есть без применения точечной записи). Синтаксис остается прежним, но на этот раз синоним назначается только полю id таблицы books, в результате ссылка на поле id таблицы authors становится однозначной.

Листинг 4.30. Определение синонимов для полей

booktown=# SELECT the_book_id, title, id, last_name

booktown-# FROM books AS b (the_book_id), authors

booktown-# WHERE author_id = id;

id | title id | last_name

190 | Little Women | 16 | Alcott

156 | The Tell-Tale Heart | 115 Рое

41472 | Practical PostgreSQL | 1212 | Worsley

2038 | Dynamic Anatomy | 1644 | Hogarth

1608 | The Cat in the Hat | 1809 | Geisel

1590 | Bartholomew and the Oobleck | 1809 | Geisel

4513 | Dune | 1866 | Herbert

4267 | 2001: A Space Odyssey | 2001 | Clarke

1501 | Goodnight Moon | 2031 | Brown

7808 | The Shining | 4156 | King

41473 | Programming Python | 7805 | Lutz

41477 | Learning Python | 7805 | Lutz

41478 | Perl Cookbook | 7806 | Christiansen

25908 | Franklin in the Dark | 15990 | Bourgeois

1234 | The Velveteen Rabbit | 25041 | Bianco

(15 rows)