我正在运行Oracle Database 11g企业版11.2.0.4.0,PL / SQL版本11.2.0.4.0,并且在获取LISTAGG函数返回期望的数据集时遇到一些问题。
这是场景:
我有一个看起来像这样的数据集
我想在一行的一列中返回MOD_CODE列中的值,例如:
AR4001,AR4002
我一直在尝试使用LISTAGG函数来完成此操作,例如:
SELECT LISTAGG(MOD_CODE,',') WITHIN GROUP (ORDER BY MOD_CODE)
FROM XOTEST_A
WHERE MOD_CODE IN ('AR4001','AR4002')
但是它不返回任何数据(请参见屏幕截图)
我在做什么错?这是更广泛场景的一部分,因此,我理想情况下想使用LISTAGG或类似的东西(我尝试使用wm_concat函数,但它返回的HUGECLOB数据类型也无法正常工作)
我已经编写了SQL以构建用于复制的方案
-- CREATE TABLE
CREATE TABLE XOTEST_A (
MOD_CODE NVARCHAR2(12),
DOM_CODE NVARCHAR2(12),
MOD_SNAM NVARCHAR2(15),
MOD_NAME NVARCHAR2(120),
SCH_CODE NVARCHAR2(6),
LEV_CODE NVARCHAR2(6),
PRS_CODE NVARCHAR2(12),
MOT_CODE NVARCHAR2(6),
MOD_CRDT NUMBER(5,2),
MOD_HOURS NUMBER(4),
MAP_CODE NVARCHAR2(12),
MOD_EREF NVARCHAR2(12),
MKS_CODE NVARCHAR2(6),
FPT_CODE NVARCHAR2(12),
ESB_CODE NVARCHAR2(6),
MOD_NPER NUMBER(2),
MOD_MOAS NVARCHAR2(1),
MOD_PMOA NVARCHAR2(1),
MEP_CODE NVARCHAR2(6),
DPT_CODE NVARCHAR2(12),
ELV_CODE NVARCHAR2(3),
ECL_CODE NVARCHAR2(3),
MOD_UTYC NVARCHAR2(3),
MOD_COGC NVARCHAR2(6),
MOD_STAT VARCHAR2(1 BYTE),
MOD_UPDD DATE,
MOD_KEYW NVARCHAR2(100),
MOD_IUSE VARCHAR2(1 BYTE),
MOD_TOCC NVARCHAR2(12),
MOD_DVNC NVARCHAR2(12),
MOD_UDF1 NVARCHAR2(15),
MOD_UDF2 NVARCHAR2(15),
MOD_UDF3 NVARCHAR2(15),
MOD_UDF4 NVARCHAR2(15),
MOD_UDF5 NVARCHAR2(15),
MOD_UDF6 NVARCHAR2(15),
MOD_UDF7 NVARCHAR2(15),
MOD_UDF8 NVARCHAR2(15),
MOD_UDF9 NVARCHAR2(15),
MOD_UDFA NVARCHAR2(15),
MOD_UDFB NVARCHAR2(15),
MOD_UDFC NVARCHAR2(15),
MOD_UDFD NVARCHAR2(15),
MOD_UDFE NVARCHAR2(15),
MOD_UDFF NVARCHAR2(15),
MOD_UDFG NVARCHAR2(15),
MOD_UDFH NVARCHAR2(15),
MOD_UDFI NVARCHAR2(15),
MOD_UDFJ NVARCHAR2(100),
MOD_UDFK NVARCHAR2(100),
MOD_VALC NVARCHAR2(12),
MOD_APRT NUMBER(5,2),
MOD_LANG NVARCHAR2(1),
MOD_ERFM NVARCHAR2(1),
MOD_MUSE VARCHAR2(1 BYTE),
MOD_FACC NVARCHAR2(6),
MOD_ISGX VARCHAR2(1 BYTE),
MOD_REGM NVARCHAR2(1),
MOD_FRID VARCHAR2(1 BYTE),
MOD_WEEI NVARCHAR2(1),
MOD_MODE NVARCHAR2(1)--,
--MOD_NOTE NCLOB
)
--INSERT VALUES INTO THE TABLE
INSERT INTO XOTEST_A (MOD_CODE,DOM_CODE,MOD_SNAM,MOD_NAME,SCH_CODE,LEV_CODE,PRS_CODE,MOT_CODE,MOD_CRDT,MOD_HOURS,MAP_CODE,MOD_EREF,MKS_CODE,FPT_CODE,ESB_CODE,MOD_NPER,MOD_MOAS,MOD_PMOA,MEP_CODE,DPT_CODE,ELV_CODE,ECL_CODE,MOD_UTYC,MOD_COGC,MOD_STAT,MOD_UPDD,MOD_KEYW,MOD_IUSE,MOD_TOCC,MOD_DVNC,MOD_UDF1,MOD_UDF2,MOD_UDF3,MOD_UDF4,MOD_UDF5,MOD_UDF6,MOD_UDF7,MOD_UDF8,MOD_UDF9,MOD_UDFA,MOD_UDFB,MOD_UDFC,MOD_UDFD,MOD_UDFE,MOD_UDFF,MOD_UDFG,MOD_UDFH,MOD_UDFI,MOD_UDFJ,MOD_UDFK,MOD_VALC,MOD_APRT,MOD_LANG,MOD_ERFM,MOD_MUSE,MOD_FACC,MOD_ISGX,MOD_REGM,MOD_FRID,MOD_WEEI,MOD_MODE/*,MOD_NOTE*/)
VALUES ('AR4001', 'SEN', 'AR4001', 'DESIGN STUDIO 1A', 'UL', '1', 'HASGRA1', 'A', 15, NULL, 'AR4001', NULL, 'AMOD', NULL, NULL, 1, 'M', 'M', NULL, 'SENDES', NULL, NULL, 'F', NULL, NULL, NULL, NULL, 'Y', NULL, NULL, NULL, '15/05/2008', 'V', 'P', NULL, 'N', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'N', NULL, NULL, NULL, NULL, NULL, NULL/*, ''*/)
COMMIT;
INSERT INTO XOTEST_A (MOD_CODE,DOM_CODE,MOD_SNAM,MOD_NAME,SCH_CODE,LEV_CODE,PRS_CODE,MOT_CODE,MOD_CRDT,MOD_HOURS,MAP_CODE,MOD_EREF,MKS_CODE,FPT_CODE,ESB_CODE,MOD_NPER,MOD_MOAS,MOD_PMOA,MEP_CODE,DPT_CODE,ELV_CODE,ECL_CODE,MOD_UTYC,MOD_COGC,MOD_STAT,MOD_UPDD,MOD_KEYW,MOD_IUSE,MOD_TOCC,MOD_DVNC,MOD_UDF1,MOD_UDF2,MOD_UDF3,MOD_UDF4,MOD_UDF5,MOD_UDF6,MOD_UDF7,MOD_UDF8,MOD_UDF9,MOD_UDFA,MOD_UDFB,MOD_UDFC,MOD_UDFD,MOD_UDFE,MOD_UDFF,MOD_UDFG,MOD_UDFH,MOD_UDFI,MOD_UDFJ,MOD_UDFK,MOD_VALC,MOD_APRT,MOD_LANG,MOD_ERFM,MOD_MUSE,MOD_FACC,MOD_ISGX,MOD_REGM,MOD_FRID,MOD_WEEI,MOD_MODE/*,MOD_NOTE*/)
VALUES ('AR4002', 'SEN', 'AR4002', 'DESIGN STUDIO 1A', 'UL', '1', 'HASGRA1', 'A', 15, NULL, 'AR4002', NULL, 'AMOD', NULL, NULL, 1, 'M', 'M', NULL, 'SENDES', NULL, NULL, 'F', NULL, NULL, NULL, NULL, 'Y', NULL, NULL, NULL, '15/05/2008', 'V', 'P', NULL, 'N', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'N', NULL, NULL, NULL, NULL, NULL, NULL/*, ''*/)
COMMIT;
-- NOW RUN THE SELECT STATEMENT
SELECT LISTAGG(MOD_CODE,',') WITHIN GROUP (ORDER BY MOD_CODE) LISTAGG_OUTPUT
FROM XOTEST_A
WHERE MOD_CODE IN ('AR4001','AR4002')
答案 0 :(得分:5)
这似乎与错误19461687和this previous question有关。如果您将查询的汇总值转储到11gR2或12cR1中,则会看到:
LISTAGG_OUTPUT
--------------------------------------------------------------------------------------------------
Typ=1 Len=25 CharacterSet=AL32UTF8: 0,41,0,52,0,34,0,30,0,30,0,31,2c,0,41,0,52,0,34,0,30,0,30,0,32
在SQL * Plus和SQL Developer中,实际值显示为:
LISTAGG_OUTPUT
----------------------------------------
A R 4 0 0 1, A R 4 0 0 2
,您将无法从SQL Developer复制该值。 (在12cR2中,零不再出现在转储中,显示的值没有空格,您可以复制它,因此该错误似乎已得到解决。)
这些空字节似乎导致Toad根本不显示该值,大概是因为它看到了第一个空字节并将其视为字符串终止符(或者无论如何都沿字符串)。
SQL Fiddle似乎可以解决这个问题,但是db <> fiddle似乎也有问题,当存在该查询时,整个Fiddle不会返回任何内容。
您可以将表列重新定义为varchar2
而不是nvarchar2
,但是由于某种原因,我认为它是该数据类型,因此可能不切实际。
因此您可以将其强制转换为查询的一部分:
SELECT LISTAGG(CAST(MOD_CODE AS VARCHAR2(12)),',')
WITHIN GROUP (ORDER BY MOD_CODE) LISTAGG_OUTPUT
FROM XOTEST_A
WHERE MOD_CODE IN ('AR4001','AR4002');
LISTAGG_OUTPUT
----------------------------------------
AR4001,AR4002
或者查看漏洞19461687的补丁是否为您解决了该问题。
答案 1 :(得分:2)
但是它不返回任何数据(请参见屏幕截图)
您的样本数据将产生预期的结果。 here is a SQL Fiddle。因此,问题不在于语法或数据库。剩下数据了。
最可能的解释是您的MOD_CODE的值与WHERE子句中的值不匹配。从屏幕截图很难分辨,但是如果您的数据具有不可见的值,例如尾随空格('AR4001 '
,'AR4002 '
),则您的WHERE子句将不返回任何行。
有两种测试方法。运行不带WHERE子句的查询。测试数据的长度-vsize(mod_code)
-或转储内容-dump(mod_code)
。