在管道分隔连接期间格式化列标题(Oracle SQL)

在管道分隔连接期间格式化列标题(Oracle SQL),sql,oracle,concatenation,alias,sqlplus,Sql,Oracle,Concatenation,Alias,Sqlplus,概述:我的任务是将Oracle数据库中的数据提取作为管道分隔的输出文本文件提供。我将使用SQLPlus在数据所在的服务器上执行此操作。通常,这项任务并不超出我的经验,但这一次,业务部门希望列标题出现 考虑我需要输出的以下五列: SELECT a.USER_NAME || '|' || a.LAST_NAME || '|' || a.FIRST_NAME || '|' || b.PRODUCT_PURCHASED || '|' || c.DATEPURCHA

概述:我的任务是将Oracle数据库中的数据提取作为管道分隔的输出文本文件提供。我将使用SQLPlus在数据所在的服务器上执行此操作。通常,这项任务并不超出我的经验,但这一次,业务部门希望列标题出现

考虑我需要输出的以下五列:

SELECT
    a.USER_NAME || '|'
    || a.LAST_NAME || '|'
    || a.FIRST_NAME || '|'
    || b.PRODUCT_PURCHASED || '|'
    || c.DATEPURCHASED
FROM ...
WHERE ... ;
此SQL工作正常,输出如下所示:

omnusruthius|ruthius|omnus|stackoverflow_prod|19-APR-16
然而,企业希望它看起来像:

USER_NM|LAST|FIRST|PROD|EFFECTIVE_DATE
omnusruthius|ruthius|omnus|stackoverflow_prod|19-APR-16
问题:因此,这里的目标基本上是输出具有自定义命名列标题(别名)的第一行,如上所示。因此,我的第一个方法是尝试以下方法:

    SELECT
    a.USER_NAME AS USER_NM || '|'
    || a.LAST_NAME AS LAST || '|'
    || a.FIRST_NAME AS FIRST || '|'
    || b.PRODUCT_PURCHASED AS PROD || '|'
    || c.DATEPURCHASED AS EFFECTIVE_DATE
    FROM ...
    WHERE ...
不幸的是,我收到:

ORA-00923:未在预期位置找到FROM关键字

我不确定这会有什么帮助,因为没有别名的原始SQL输出不会在第一行显示列标题。记住,这是通过命令行(SQLPlus)实现的,而不是Toad或其他RDM

于是我试着:

SELECT 
   'USER_NM', 'LAST', 'FIRST', 'PROD', 'EFFECTIVE_DATE' FROM DUAL
UNION ALL
SELECT
    a.USER_NAME || '|'
    || a.LAST_NAME || '|'
    || a.FIRST_NAME || '|'
    || b.PRODUCT_PURCHASED || '|'
    || c.DATEPURCHASED
FROM ...
WHERE ...
这会产生以下错误:

ORA-01789:查询块的结果列数不正确

我觉得离解决方案很近,我在这里错过了什么?任何帮助都将不胜感激

编辑:这只是给未来读者的一个提示,这里的两个答案都将帮助您解决这个问题,但经过进一步调整,我意识到我们都在过度思考解决方案。我不打算提出一个新的解决方案,因为变化是微不足道的,但是考虑做以下的替代:

SELECT 'USER_NM|LAST|FIRST|PROD|EFFECTIVE_DATE' FROM DUAL;
SELECT a.USER_NAME AS USER_NM || '|'
|| a.LAST_NAME AS LAST || '|'
|| a.FIRST_NAME AS FIRST || '|'
|| b.PRODUCT_PURCHASED AS PROD || '|'
|| c.DATEPURCHASED AS EFFECTIVE_DATE
FROM ...
WHERE ...
ORDER BY ... ;

这里的关键是在SQL*Plus中使用分号。第一个SELECT语句完全独立于第二个SELECT语句;不需要联合,因为第一个查询的输出会在紧接第二个查询的输出之前自动显示。两者都可以有自己的规则,如果后一个查询要复杂得多,这将非常方便。我可以确认上面的查询正在工作,我很惊讶我花了这么长时间才实现…

连接时,请确保标题是单个字符串。因为要将列中的值连接到一行上

如果使用逗号分隔,正如您在问题中所做的那样,结果块还应该有5列,但事实并非如此

SELECT 
   'USER_NM|LAST|FIRST|PROD|EFFECTIVE_DATE' FROM DUAL
UNION ALL
SELECT
    a.USER_NAME || '|'
    || a.LAST_NAME || '|'
    || a.FIRST_NAME || '|'
    || b.PRODUCT_PURCHASED || '|'
    || c.DATEPURCHASED
FROM ...
WHERE ...
编辑:也可以对列进行排序

SELECT 'USER_NM|LAST|FIRST|PROD|EFFECTIVE_DATE' FROM DUAL
UNION ALL
SELECT * FROM (
SELECT
    a.USER_NAME || '|'
    || a.LAST_NAME || '|'
    || a.FIRST_NAME || '|'
    || b.PRODUCT_PURCHASED || '|'
    || c.DATEPURCHASED
FROM ...
WHERE ...
ORDER BY DATEPURCHASED) --add any other columns needed

由于您使用SQL*Plus标记了问题,因此可以使用生成标题,从而避免了使用union对结果排序的复杂性:

PROMPT USER_NM|LAST|FIRST|PROD|EFFECTIVE_DATE

SELECT
a.USER_NAME AS USER_NM || '|'
|| a.LAST_NAME AS LAST || '|'
|| a.FIRST_NAME AS FIRST || '|'
|| b.PRODUCT_PURCHASED AS PROD || '|'
|| c.DATEPURCHASED AS EFFECTIVE_DATE
FROM ...
WHERE ...
ORDER BY ...
这就把标题从SQL中去掉,放到了客户机领域,而客户机领域可以说是它所属的领域。这也适用于SQLDeveloper,其他客户端也可以执行类似的操作。如果您自己从另一个客户机运行查询,或者通过JDBC或其他任何方式运行查询,那么它将不起作用;但是,在这种情况下,运行查询的任何东西都可以(也可能应该)提供头


如果您还没有,您也可以考虑执行<代码>设置标题> <代码>或<代码>设置PaxeSex 0 <代码>,以抑制来自查询本身的列标题(尽管从您所说的已经做过);还有可能

设置EMBED OFF
,但我认为这是不必要的,除非您执行单独的查询来生成标题行。

如果您不需要排序,这将很好。如果您需要按用户名或姓氏进行排序,则标题行将落在任何位置。这里的排序是什么意思?查看编辑后的答案,并进行排序。OP没有提到,但他很可能需要列表“排序依据”(sorted by),以某种方式(“sorted”-我的错,应该说“ordered by”)。如果没有ORDERBY子句,行将不会以任何方式排序,并且不能保证标题行位于顶部。添加了ORDERBY子句后,几乎可以肯定标题行不会位于顶部。ORDER BY仅在联合之后处理,而不是在联合之前!你以前试过这个吗?我建议你自己检查一下。对结果进行排序。不是字符串头.Vkp,谢谢您的快速响应。这绝对有助于我进步@mathguy的假设是正确的,即我需要订购此数据输出。我很抱歉没有提前说明。如果有帮助的话,我确切地知道它将被排序的字段:date。此摘录将是每晚进行的作业,获取前一天的数据并向业务部门提供报告。编辑:刚刚看到你的编辑。当我有一些数据要测试时,我会报告。使用PROMPT可以很好地工作。你能详细说明一下你文章的第二部分关于出发和出发的内容吗?现在我有:设置DEFINE ON、设置PAGESIZE 0、设置HEADING ON、设置FEEDBACK OFF、设置ECHO OFF、设置SQLBLANKLINES OFF、设置trimpool ON、设置TRIMOUT ON、设置LINESIZE 2000如果需要设置embed ON来防止出现空行,我无法立即记住,但我认为这只是在有两个查询的情况下,而不是提示。看来你可以忽略这一点,。您的
set pagesize 0
胜过
set heading on
——设置为零或分页符等。因此
set head[ing]off
也将是多余的。我同意这个答案,因为它针对SQL*Plus进行了优化,并且独立于未来潜在的业务需求变化(即,在不同字段上排序)。此外,与严格的无空格、全大写的SQL列标题相比,它实际上为顶行的命名和样式(即小写、空格合法等)提供了更大的灵活性。最终,这个SQL被假脱机到一个文本文件,所以这个实现非常适合我的需要。非常感谢你的帮助@OmnusRuthius-vkp的方法也允许您在标题行中使用任何您喜欢的内容,因为它只是一个字符串文本。您不受原始列名或对象命名规则的限制。(实际上,它还允许更长的标题;提示符将限制您<2500。)