Oracle - select语句中的动态列名

时间:2009-05-13 21:26:16

标签: oracle

问题:

是否可以根据其结果集中的值更改select语句中的列名?

例如,如果结果集中的year值小于1950,请将列命名为OldYear,否则请将列命名为NewYear。结果集中的year值保证对所有记录都相同。

我认为这是不可能的,但这是我尝试测试这个想法的失败:

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

5 个答案:

答案 0 :(得分:5)

您不能更改结果集的每一行的列名。这是关系数据库的基础。列的名称是表“header”的一部分,名称适用于其下所有行的列。


评论:好的,OP Americus可能意味着结果恰好是一行。但无论如何,SQL没有语法来支持动态列别名。列别名在查询中必须是常量。

即使动态SQL也无济于事,因为您必须运行两次查询。一次获取值,第二次使用不同的列别名重新运行查询。

答案 1 :(得分:4)

在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 :(得分:2)

没有充分的理由动态更改列名 - 它类似于过程代码中变量的名称 - 它只是您稍后可能在代码中引用的标签,因此您不希望它更改在运行时。

我猜你真正想要的是一种根据数据格式化输出(例如在报告中打印)的方法。在这种情况下,我会将标题文本生成为查询中的单独列,例如:

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

然后调用过程将获取为mydata和myheader返回的值,并根据需要格式化输出。

答案 3 :(得分:1)

你需要类似的东西:

select 'select ' || CASE WHEN YEAR<1950 THEN 'OLDYEAR' ELSE 'NEWYEAR' END  || ' FROM TABLE 1' from TABLE_WITH_DATA

答案 4 :(得分:0)

此解决方案要求您从.bat文件或使用具有相应Oracle凭据的其他方法启动SQLPLUS和.sql文件。 .bat文件可以从服务器计划任务,Control-M作业等手动启动...

输出是.csv文件。这还要求您将输出中的所有逗号替换为输出中的某些其他字符或冒险列/数据不匹配。

技巧是在两个不同的SELECT语句中选择列标题和数据。

它并不完美,但它确实有效,并且它与我在发展环境之外的动态列标题中找到的标准Oracle SQL最接近。我们广泛使用它来为用户生成定期的每日/每周/每月报告,而无需借助GUI。输出保存到共享网络驱动器目录/ 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.