我需要创建一个带有聚合列的视图 nvarchar2(4000)
在 Oracle 11g 中。
我拥有的:
Table1
每一列类型nvarchar2(4000)
:
Col_Name txt_value
X a
X b
X c
Y a
Y c
Run Code Online (Sandbox Code Playgroud)
结果应该是这样的视图,两列类型为nvarchar2(4000)
:
Col_Name txt_value
X a;b;c
Y a;c
Run Code Online (Sandbox Code Playgroud)
我试过:
CREATE VIEW dict (col_Name, txt_value) AS
SELECT col_Name, LISTAGG (txt_value,';') WITHIN GROUP (ORDER BY txt_value)
FROM table1
GROUP BY col_Name
Run Code Online (Sandbox Code Playgroud)
唯一的问题是LISTAGG()
将结果转换为varchar2(4000)
我需要的 bit类型的列nvarchar2
。
正如文档所描述的:
如果度量列是 RAW,则返回数据类型是 RAW;否则返回值为 VARCHAR2。
因此,除非您将列作为 传递,否则RAW
结果将是VARCHAR2
,这还不够好,因为这意味着转换过程中数据丢失。
LISTAGG
与VARCHAR2
or 一起使用RAW
,所以简单地说,您需要将所有内容转换为RAW
,然后将结果转换回NVARCHAR2
.
下面是一个例子:
SQL> select parameter, value from nls_database_parameters where parameter like '%CHARACTERSET';
PARAMETER VALUE
------------------------------ ------------------------------
NLS_CHARACTERSET EE8ISO8859P2
NLS_NCHAR_CHARACTERSET AL16UTF16
Run Code Online (Sandbox Code Playgroud)
我的默认字符集不支持€
符号。
SQL> create table t1 (id number, c1 varchar2(20), c2 nvarchar2(20));
Table created.
SQL> insert into t1 values (1, 'A', 'A');
1 row created.
SQL> insert into t1 values (2, NCHR(8364), NCHR(8364));
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t1;
ID C1 C2
---------- -- --
1 A A
2 ? €
Run Code Online (Sandbox Code Playgroud)
如您所见,我?
使用VARCHAR2
.
如果我只是尝试LISTAGG
在NVARCHAR2
列上使用,则在转换过程中数据将丢失:
select
listagg(c2, ',') within group (order by id) as list1
from t1;
LIST1
----------
A, ?
Run Code Online (Sandbox Code Playgroud)
如果我尝试转换结果,仍然不够好,因为在转换为VARCHAR2
:
select
cast(listagg(c2, ',') within group (order by id) as nvarchar2(20)) as list2
from t1;
LIST2
----------
A, ?
Run Code Online (Sandbox Code Playgroud)
剩下的选项是转换为RAW
:
select
utl_raw.cast_to_nvarchar2(listagg(utl_raw.cast_to_raw(c2), utl_raw.cast_to_raw(',')) within group (order by id)) as list3
from t1;
LIST3
----------
A?
Run Code Online (Sandbox Code Playgroud)
转换VARCHAR2
分隔符会弄乱数据,我还需要在 中指定分隔符NVARCHAR2
,因此','
我必须使用N','
:
select
utl_raw.cast_to_nvarchar2(listagg(utl_raw.cast_to_raw(c2), utl_raw.cast_to_raw(N',')) within group (order by id)) as list4
from t1;
LIST4
----------
A,€
Run Code Online (Sandbox Code Playgroud)