在管道分隔串联期间格式化列 Headers (Oracle SQL)
Format Column Headers during Pipe Delimited Concatenation (Oracle SQL)
概述: 我的任务是提供从 Oracle 数据库中提取的数据作为 pipe-delimited 输出文本文件。我将使用 SQLPlus 在数据所在的服务器上执行此操作。按说这个任务不超出我的经验,但是这次,业务要求列 headers 出现。
考虑我需要输出的以下五列:
SELECT
a.USER_NAME || '|'
|| a.LAST_NAME || '|'
|| a.FIRST_NAME || '|'
|| b.PRODUCT_PURCHASED || '|'
|| c.DATEPURCHASED
FROM ...
WHERE ... ;
这个 SQL 工作正常,输出如下:
omnusruthius|ruthius|omnus|Whosebug_prod|19-APR-16
但是,企业希望它看起来像:
USER_NM|LAST|FIRST|PROD|EFFECTIVE_DATE
omnusruthius|ruthius|omnus|Whosebug_prod|19-APR-16
问题: 所以这里的objective本质上就是输出第一行有custom-named列headers(别名),如图多于。所以我的第一种方法是尝试类似的方法:
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 keyword not found where expected
我不确定这有什么帮助,因为没有别名的原始 SQL 输出无论如何不会在第一行显示列 headers。请记住,这是通过命令行 (SQLPlus),而不是 Toad 或其他一些 RDMS。
然后我尝试了:
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: query block has incorrect number of result columns
我觉得很接近解决方案,我在这里缺少什么?任何帮助将不胜感激!
编辑: 只是对未来的说明 reader,这里的两个答案都将帮助您解决这个问题,但在进一步调整后,我意识到我们都一直在考虑解决方案。我不打算提出新的解决方案,因为更改微不足道,但请考虑执行以下操作:
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 语句完全独立于第二个;不需要 UNION,因为第一个查询的输出会自动显示在第二个查询的输出之前。两者都可以有自己的规则,如果您的后一个查询要复杂得多,这将特别方便。我可以确认上面的查询是有效的,我很惊讶我花了这么长时间才意识到...
连接时确保 header 是单个字符串。因为您将列中的值连接到一行中。
如果使用逗号分隔,就像您在问题中使用的那样,结果块也应该有 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 标记了问题,您可以使用 the PROMPT command 生成 header,这避免了使用并集对结果进行排序的复杂性:
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 中移出并进入客户领域,它可以说属于该领域。这在 SQL Developer 中也有效,其他客户端也可以做类似的事情。如果您 运行 自己从另一个客户端查询,或通过 JDBC 或其他任何方式查询,它将不起作用;但是无论 运行 查询是什么,在这种情况下也可以(也许应该)提供 header。
如果您还没有这样做,您还可以考虑执行 SET HEADING OFF
或 SET PAGESIZE 0
以从查询本身中抑制列标题(尽管从您所说的您已经在这样做) ;并且可能 SET EMBED OFF
,但我认为这不是必需的,除非您执行单独的查询来生成 header 行。
概述: 我的任务是提供从 Oracle 数据库中提取的数据作为 pipe-delimited 输出文本文件。我将使用 SQLPlus 在数据所在的服务器上执行此操作。按说这个任务不超出我的经验,但是这次,业务要求列 headers 出现。
考虑我需要输出的以下五列:
SELECT
a.USER_NAME || '|'
|| a.LAST_NAME || '|'
|| a.FIRST_NAME || '|'
|| b.PRODUCT_PURCHASED || '|'
|| c.DATEPURCHASED
FROM ...
WHERE ... ;
这个 SQL 工作正常,输出如下:
omnusruthius|ruthius|omnus|Whosebug_prod|19-APR-16
但是,企业希望它看起来像:
USER_NM|LAST|FIRST|PROD|EFFECTIVE_DATE
omnusruthius|ruthius|omnus|Whosebug_prod|19-APR-16
问题: 所以这里的objective本质上就是输出第一行有custom-named列headers(别名),如图多于。所以我的第一种方法是尝试类似的方法:
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 keyword not found where expected
我不确定这有什么帮助,因为没有别名的原始 SQL 输出无论如何不会在第一行显示列 headers。请记住,这是通过命令行 (SQLPlus),而不是 Toad 或其他一些 RDMS。
然后我尝试了:
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: query block has incorrect number of result columns
我觉得很接近解决方案,我在这里缺少什么?任何帮助将不胜感激!
编辑: 只是对未来的说明 reader,这里的两个答案都将帮助您解决这个问题,但在进一步调整后,我意识到我们都一直在考虑解决方案。我不打算提出新的解决方案,因为更改微不足道,但请考虑执行以下操作:
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 语句完全独立于第二个;不需要 UNION,因为第一个查询的输出会自动显示在第二个查询的输出之前。两者都可以有自己的规则,如果您的后一个查询要复杂得多,这将特别方便。我可以确认上面的查询是有效的,我很惊讶我花了这么长时间才意识到...
连接时确保 header 是单个字符串。因为您将列中的值连接到一行中。
如果使用逗号分隔,就像您在问题中使用的那样,结果块也应该有 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 标记了问题,您可以使用 the PROMPT command 生成 header,这避免了使用并集对结果进行排序的复杂性:
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 中移出并进入客户领域,它可以说属于该领域。这在 SQL Developer 中也有效,其他客户端也可以做类似的事情。如果您 运行 自己从另一个客户端查询,或通过 JDBC 或其他任何方式查询,它将不起作用;但是无论 运行 查询是什么,在这种情况下也可以(也许应该)提供 header。
如果您还没有这样做,您还可以考虑执行 SET HEADING OFF
或 SET PAGESIZE 0
以从查询本身中抑制列标题(尽管从您所说的您已经在这样做) ;并且可能 SET EMBED OFF
,但我认为这不是必需的,除非您执行单独的查询来生成 header 行。