Подтвердить что ты не робот

Существует ли общий способ обхода, чтобы выразить производный список столбцов в Oracle (и MySQL)?

Многие базы данных SQL поддерживают то, что стандарт SQL вызывает <derived column list>. Такие базы данных включают по меньшей мере CUBRID, Derby, Firebird, HSQLDB, Postgres, SQL Server и Sybase SQL Anywhere. A (упрощенный) из спецификации SQL: 2008

7.6 <table reference>

Format
<table reference> ::=
    <table or query name> [ [ AS ] <correlation name>
      [ <left paren> <derived column list> <right paren> ] ]
  | <derived table> [ AS ] <correlation name>
      [ <left paren> <derived column list> <right paren> ]

Это означает, что я могу выразить такие вещи (например, в Postgres, который соответствует стандартам)

-- Rename a <table or query name> to u(b)
with t(a) as (select 1)
select * from t as u(b)

-- Rename a <derived table> to u(b)
select * from (select 1) as u(b)

Теперь, согласно документации Oracle, я не могу переименовать столбцы, используя спецификацию <derived column list>. Я мог бы, конечно, переименовать таблицы и столбцы отдельно, например:

-- Rename a <table or query name> to u(b)
with t(a) as (select 1 from dual)
select u.a b from t u;

-- Rename a <derived table> to u(b)
select u.a b from (select 1 a from dual) u;

Но для этого требуется больше знаний о производной таблице (имена фактических столбцов), чем предыдущий синтаксис. Кроме того, переименованные столбцы будут доступны только после проецирования (например, в предложении ORDER BY), а не в любых других предложениях, включая сам проект.

Существует ли более общий способ переименования таблиц И столбцов, как предлагает стандарт SQL, в Oracle (а также MySQL)? В частности, это может быть полезно для таких вещей, как переназначение массива, переименование таблицы pivot/unpivot, встраивание сложных подзапросов, переименование результатов из табличных функций и т.д.

N.B: Пожалуйста, не сосредотачивайтесь на приведенных выше примерах слишком много. Они действительно здесь, чтобы проиллюстрировать проблему. Реальные запросы гораздо сложнее, поэтому я ищу очень общий способ реализации переименования в u(b)

ПРИМЕЧАНИЕ. Я все еще ищу решение, которое работает в базе данных, например MySQL. Связанный с этим вопрос:
Как выбрать неустановленный числовой литерал из подвыборки

4b9b3361

Ответ 1

Для решения MySQL вы можете использовать UNION для установки имен всех столбцов в терминах запроса с нулевой строкой, а затем затем запросить что-то более сложное:

SELECT null AS a, null AS b, null AS c FROM dual WHERE false
UNION ALL
SELECT <expr>, <expr>, <expr>
FROM <realtable>...

Только первый термин запроса UNION определяет имена столбцов всего запроса. Имена столбцов (или их отсутствие) в последующих запросах не влияют на конечные имена столбцов.

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

Ответ 2

Поскольку вы ДОЛЖНЫ знать количество столбцов, но не обязательно имена столбцов, вы можете использовать предложение WITH, чтобы переименовать эти столбцы, как вам угодно. Например (WITH работает в Oracle и SQL Server, не имеет экземпляра MySQL):

WITH t(x,y,z) as (select * from TABLE(fn_returning_xcols(3)))
select * from t;

Здесь мы не знаем имена столбцов во внутреннем select, но мы можем переименовать их во внешнем разделе WITH.

Другой пример использования PIVOT в Oracle:

WITH t(a,b,c,d,e) as 
(
 select * from 
 (
  select level as levl from dual connect by level <= 5
 )
 PIVOT(max(levl) as l for levl in (1,2,3,4,5))
)
select * from t;

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

Ответ 3

Как было предложено пользователем tbone here, обычные табличные выражения являются хорошим решением моей проблемы, по крайней мере для Oracle. Для полноты, вот мой пример, написанный с использованием CTE в Oracle

-- Rename a <derived table> to u(b) with Oracle
with u(b) as (select 1 from dual) 
select u.b from u

-- Rename a <derived table> to u(b) with H2, which only knows recursive CTEs
-- Thanks to a comment by user a_horse_with_no_name
with recursive u(b) as (
  select 1
  union all
  select null where false
)
select u.b from u