В SQL данные таблицы T и S имеют, скажем, одну и ту же схему:
CREATE TABLE "T" ("ID" INTEGER, "Salary" REAL);
CREATE TABLE "S" ("ID" INTEGER, "Salary" REAL);
мы можем объединить два отношения с помощью команды
(SELECT * FROM "S") UNION (SELECT * FROM "T");
но следующая команда выдает ошибку:
"S" UNION "T";
Сообщение об ошибке в SQLite: near "UNION": syntax error
Сообщение об ошибке в SQL Server: Incorrect syntax near the keyword 'UNION'.
Почему мы не можем использовать последнюю команду? Говоря алгебраически, оператор объединения принимает два табличных операнда и выводит в результате еще одну таблицу. Значит "S" UNION "T" должно работать. Это аналогично тому, как операторы выбора и проецирования берут табличный операнд и выводят другую таблицу.
Я понимаю, что хотя результат оператора SELECT должен алгебраически представлять собой таблицу, на практике это «виртуальная таблица». Насколько я понимаю из книги CJ Date «Введение в системы баз данных» (8-е изд.), такие таблицы, как S и T выше, являются «базовыми relvars/отношениями», тогда как виртуальные таблицы, такие как (SELECT * FROM "S") и (SELECT * FROM "T"), являются «производными отношениями»; и что обе таблицы (базовая и производная) считаются таблицами. Так почему же они не действуют так же, когда на них действует UNION?
Интересно, что после того, как мы присвоим имена view1 и view2 выходам (SELECT * FROM "S") и (SELECT * FROM "T") соответственно для создания представлений,
CREATE VIEW "view1" AS SELECT * FROM "S";
CREATE VIEW "view2" AS SELECT * FROM "T";
мы снова получим ошибки, если передадим представления UNION в качестве операндов:
"view1" UNION "view2";
Сообщение об ошибке в SQLite: near "UNION": syntax error
Сообщение об ошибке в SQL Server: Incorrect syntax near 'view1'.
Что происходит? Почему операнды обязательно должны быть операторами SELECT?
Потому что именно так был определен язык. (А SQL — плохо спроектированный язык.) Это вопрос истории (языка программирования), а не практического программирования. Вопрос «почему» в отношении языковых спецификаций по-прежнему считается «в первую очередь основанным на мнении», если на него могут быть официальные ответы?


Хотя реляционные базы данных построены на основе реляционной алгебры, они не одинаковы, особенно в реальных реализациях. Некоторые версии некоторых СУБД даже не соответствуют стандарту SQL (на самом деле от них не требуется полная его поддержка, чтобы заявлять о совместимости, некоторые функции являются необязательными).
В любом случае, стандарт SQL определяет оператор UNION так, как вы ожидаете:
<non-join query expression> ::=
<non-join query term>
| <query expression> UNION [ ALL ] [ <corresponding spec> ] <query term>
если все развернуть:
<query term> ::= <non-join query term><non-join query term> ::= <non-join query primary><non-join query primary> ::= <simple table><simple table> ::= <explicit table><explicit table> ::= TABLE <table name>
<explicit table>TABLE <table name>эквивалентно<query expression>( SELECT * FROM <table name> )
Итак, согласно стандарту вы должны иметь возможность использовать такой синтаксис:
TABLE T UNION TABLE S
но фактическая реализация языка SQL зависит от разработчиков СУРБД, я не знаю никого, кто бы поддерживал такие явные табличные операторы, кстати, то же самое для UNION JOIN, поэтому ответьте на ваш вопрос Why should the operands for UNION be SELECT statements and not tables? - потому что разработчики решили не следовать стандарт.
«определяет оператор UNION так, как вы ожидаете» противоречит «вы должны иметь возможность использовать такой синтаксис, как:TABLE T UNION TABLE S».
@philipxy, когда мы все разворачиваем, мы можем сказать, что стандарт sql определяет объединение (один из его вариантов) как <explicit table> UNION <explicit table> - это то, что OP ожидал работать
Нет, они ожидают, что T UNION S сработает. <явная таблица> — это не просто имя таблицы.
@philipxy OP хочет использовать имена таблиц без оператора выбора, предполагается, что синтаксис будет T UNION S, я хочу сказать, что в соответствии со стандартом это возможно (использовать имена таблиц без выбора), с немного другим синтаксисом, но на практике даже это не работает
@IłyaBursov Итак, вывод оператора SELECT, согласно стандарту, представляет собой explicit table. Напротив, вызов таблицы по ее table name не возвращает explicit table. Что он возвращает?
@Ardy <явная таблица> — это определенный вид табличного выражения в грамматике, представляющий собой токен TABLE, за которым следует выражение <имя таблицы>. <имя таблицы> — это имя базовой таблицы. Строки, отмеченные ::=, описывают грамматику.
Оператор @Ardy select — это <query expression> в грамматике, а <explicit table> эквивалентно <query expression>, что означает, что вы должны иметь возможность использовать TABLE name вместо SELECT *.. в соответствии со стандартом, но на самом деле...
у них такая же схема
Если у вас есть две базовые таблицы с одинаковой схемой, вам следует спросить, почему это не одна таблица? (Возможно, с дополнительным столбцом, указывающим, какой реальный сценарий приводит к появлению строки в таблице.)
Рассмотрим более обычный стиль запроса:
SELECT * FROM T WHERE X = 1
UNION
SELECT * FROM T WHERE X = 2;
≡
SELECT * FROM T WHERE X = 1 OR X = 2;
≡
SELECT * FROM T WHERE X IN (1, 2);
Обычно UNION предназначен для OR объединения результатов различных условий выбора в одной базовой таблице — следовательно, операнды, естественно, будут иметь одну и ту же схему.
UNION— это ключевое слово SQL, которое похоже, но не совпадает с оператором объединения теории множеств ∪.