Oracle - динамическое имя столбца в операторе выбора - PullRequest
8 голосов
/ 14 мая 2009

Вопрос:

Можно ли изменить имя столбца в операторе выбора на основе значения в его наборе результатов?

Например, если значение year в наборе результатов меньше 1950, назовите столбец OldYear, в противном случае назовите столбец NewYear. Значение year в наборе результатов гарантированно будет одинаковым для всех записей.

Я думаю, что это невозможно, но вот моя неудачная попытка проверить идею:

select 1 as  
(case  
when 2 = 1 then "name1";  
when 1 = 1 then "name2")  
from dual; 

Ответы [ 5 ]

5 голосов
/ 14 мая 2009

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


Комментарий: хорошо, возможно, OP Americus означает, что результат, как известно, ровно в одну строку. Но независимо от того, SQL не имеет синтаксиса для поддержки псевдонима динамического столбца. Псевдонимы столбцов должны быть постоянными в запросе.

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

4 голосов
/ 11 июля 2012

«Правильный» способ сделать это в SQL - это иметь оба столбца и иметь неподходящий столбец, равный NULL, например:

SELECT
   CASE WHEN year < 1950 THEN year ELSE NULL END AS OldYear,
   CASE WHEN year >= 1950 THEN year ELSE NULL END AS NewYear
FROM some_table_with_years;
2 голосов
/ 15 мая 2009

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

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

SELECT 1 AS mydata
      ,case
          when 2 = 1 then 'name1'
          when 1 = 1 then 'name2'
       end AS myheader
FROM dual; 

Тогда вызывающая процедура будет принимать значения, возвращенные для mydata и myheader, и форматировать их для вывода в соответствии с требованиями.

1 голос
/ 14 мая 2009

Вам понадобится что-то похожее на это:

select 'select ' || CASE WHEN YEAR<1950 THEN 'OLDYEAR' ELSE 'NEWYEAR' END  || ' FROM TABLE 1' from TABLE_WITH_DATA
0 голосов
/ 21 марта 2018

Для этого решения необходимо запустить SQLPLUS и файл .sql из файла .bat или использовать другой метод с соответствующими учетными данными Oracle. Файл .bat может быть запущен вручную, с запланированной задачи сервера, задания Control-M и т. Д ...

Вывод в формате .csv. Для этого также необходимо заменить все запятые в выходных данных другими символами или столбцом риска / несоответствием данных в выходных данных.

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

Он не идеален, но он работает, и он наиболее близок к стандартному Oracle SQL, который я нашел для динамического заголовка столбца вне среды разработки. Мы широко используем это для создания регулярных ежедневных / еженедельных / ежемесячных отчетов для пользователей, не прибегая к графическому интерфейсу. Вывод сохраняется в общую сетевую директорию / Sharepoint.

        REM BEGIN runExtract1.bat file -----------------------------------------
        sqlplus username/password@database @C:\DailyExtracts\Extract1.sql > C:\DailyExtracts\Extract1.log

        exit
        REM END runExtract1.bat file -------------------------------------------

        REM BEGIN Extract1.sql file --------------------------------------------
        set colsep ,
        set pagesize 0
        set trimspool on
        set linesize 4000

        column dt new_val X 
        select to_char(sysdate,'MON-YYYY') dt from dual; 

        spool c:\DailyExtracts\&X._Extract1.csv

        select '&X-Project_id', 'datacolumn2-Project_Name', 'datacolumn3-Plant_id' from dual;

        select 
          PROJ_ID
          ||','||
          replace(PROJ_NAME,',',';')--  "Project Name"
          ||','||
          PLANT_ID--  "Plant ID"
         from PROJECTS
         where ADDED_DATE >= TO_DATE('01-'||(select to_char(sysdate,'MON-YYYY') from dual));

        spool off
        exit
        /
        REM ------------------------------------------------------------------


CSV OUTPUT (opened in Excel and copy/pasted):

old   1: select '&X-Project_id'  'datacolumn2-Project_Name'  'datacolumn3-Plant_id' from dual
new   1: select 'MAR-2018-Project_id'    'datacolumn2-Project_Name'  'datacolumn3-Plant_id' from dual
MAR-2018-Project_id datacolumn2-Project_Name    datacolumn3-Plant_id

    31415   name1   1007
    31415   name1   2032
    32123   name2   3302
    32123   name2   3384
    32963   name3   2530
    33629   name4   1161
    34180   name5   1173
    34180   name5   1205
    ...
    ...
    etc...

    135 rows selected.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...