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

#sql #oracle #ora-00904

#sql #Oracle #ora-00904

Вопрос:

 Table Meta:
-------------------------------------
type                  tab_name
new                   tab_news
sports                tab_sps

Table tab_news
------
id

Table tab_sps
-------------------
id
xx
  

Теперь я хочу использовать

 SELECT id 
  FROM (SELECT tab_name 
          FROM Meta 
         WHERE type = 'news');
  

Но это не работает, есть идеи?

Комментарии:

1. @OMG Ponies — Операционная система хочет получить все данные из таблицы tab_news. Вместо этого OP получает единственную запись из Meta-таблицы.

2. Привет, я обновляю сообщение, «BiggsTRC» правильно, я хочу получить записи таблицы tab_news. И ошибка «ошибка ora: 09004, недопустимый идентификатор «id»);

3. @OMG Ponies — Да, если вы хотели сделать это во время разработки. Однако операционная система хочет выполнить поиск данных из разных таблиц на основе значения в таблице. Например, при следующем запуске запроса вместо этого может быть указано перейти к таблице tab_sps. OP хочет, чтобы запрос изменялся во время выполнения на основе информации в базе данных.

4. Поддерживает ли oracle динамический sql?

5. @Conrad Frix: Да, Oracle поддерживает динамический SQL. Подробности смотрите в моем ответе.

Ответ №1:

SQL не поддерживает переменную / etc для имени таблицы — единственное средство поддержки того, что вы запрашиваете, — это использование динамического SQL:

 FOR i IN (SELECT tab_name
            FROM META m
           WHERE m.type = ?) LOOP
  EXECUTE IMMEDIATE 'SELECT * FROM '|| i.tab_name ||'';
END LOOP;
  

Комментарии:

1. Ошибка ORA-00904 связана с тем, что вы не можете ссылаться на столбцы, которые не существуют в таблице или производной таблице / встроенном представлении.

Ответ №2:

Синтаксическая структура, которую вы пытаетесь использовать, не выполняет то, что вы хотите. То, что появляется в предложении FROM, является набором данных. Это может быть таблица или представление. В вашем случае набор данных является подмножеством «Meta»; в частности, столбец «tab_name» для строк с типом «новости».

 SELECT id 
  FROM (SELECT tab_name 
          FROM Meta 
         WHERE type = 'news');
  

SQL в основном ориентирован на множество. Кажется, вы хотите, чтобы «tab_name» возвращал «указатель» или ссылку на набор данных. Это предполагает более объектно-ориентированный подход. Вместо имя_таблицы функция select from Meta будет возвращать экземпляры объекта, а оболочка будет использовать метод для этого объекта для извлечения деталей. Это было бы скорее

 SELECT tab_name.getId()
FROM Meta
Where type = 'news';
  

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

Ответ №3:

Я не верю, что то, чего вы пытаетесь достичь, возможно. Если вы работаете с языком программирования с этими данными, вы могли бы сначала вернуть значение подзапроса, а затем создать новую инструкцию SQL для нужного вам запроса. Однако построение динамического запроса внутри SQL подобным образом представляется невозможным.

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

Комментарии:

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

Ответ №4:

Попробуйте изменить псевдоним подзапроса.

 select * from  (select tab_name from Meta where type='news') as my_sub_query;
  

Комментарии:

1. Это не дало бы желаемых результатов. В нем все равно будет указана только одна запись из Meta-таблицы вместо таблицы, которую хотел OP.