oracle 对简单排序方式和 listagg 排序方式的排序方式不同
oracle sorts differently on simple order by and listagg's order by
Oracle Database 19c 标准版 2 发行版 19.0.0.0.0 - 生产
select letter from (
select 'A' as letter from dual union all
select 'Á' as letter from dual union all
select 'B' as letter from dual union all
select 'C' as letter from dual ) t
order by letter;
结果(没问题):
A
Á
B
C
但是有了这个
select listagg(letter,', ') within group (order by letter) from (
select 'A' as letter from dual union all
select 'Á' as letter from dual union all
select 'B' as letter from dual union all
select 'C' as letter from dual ) t;
结果字母顺序不同:
A, B, C, Á
后一种情况是简单的 Oracle 错误吗?
(我没有说任何关于 NLS 的事情。我认为这些查询应该独立于 NLS 以相同的方式工作。)
更新:
澄清:
我在同一个连接中 运行 在 SqlDeveloper 中一个接一个地查询这些查询。
NLS_SORT HUNGARIAN
NLS_COMP BINARY
(如果@MT0 的回答是解决方案,那么恕我直言,这是 oracle 中的一个错误,在简单的 order by 子句和 listagg 调用上使用不同的默认 NLS 设置。)
字母的顺序主要取决于 NLS_SORT
,所以您在邮件末尾所说的是完全错误的。
主要问题是 - 您是否在具有所有相同 NLS 设置的完全相同的系统上得到了那些相互矛盾的结果?如果是这样,那就是 LISTAGG
中 ORDER BY
子句的实现中的错误。最好有一个测试用例 - 向我们展示您的 NLS 设置(select * from v$nls_parameters
的结果),紧接着是两个查询及其输出。为了更好地衡量,还显示 select * from v$version
(告诉我们您的数据库版本)。
您需要提供 NLS_SORT
设置:
select listagg(letter,', ')
within group (order by NLSSORT(letter, 'NLS_SORT=BINARY_AI')) AS letters
from (
select 'A' as letter from dual union all
select 'Á' as letter from dual union all
select 'B' as letter from dual union all
select 'C' as letter from dual
) t;
输出:
LETTERS
A, Á, B, C
注意:LISTAGG
似乎没有在其 ORDER BY
子句中使用会话 NLS_SORT
设置;但是你可以像上图那样直接传入
如果要使用会话参数(而不是特定值):
select listagg(letter,', ')
within group (
order by NLSSORT(
letter,
( SELECT 'NLS_SORT='||value
FROM NLS_SESSION_PARAMETERS
WHERE parameter = 'NLS_SORT' )
)
) AS letters
from (
select 'A' as letter from dual union all
select 'Á' as letter from dual union all
select 'B' as letter from dual union all
select 'C' as letter from dual
) t;
db<>fiddle here
Oracle Database 19c 标准版 2 发行版 19.0.0.0.0 - 生产
select letter from (
select 'A' as letter from dual union all
select 'Á' as letter from dual union all
select 'B' as letter from dual union all
select 'C' as letter from dual ) t
order by letter;
结果(没问题):
A
Á
B
C
但是有了这个
select listagg(letter,', ') within group (order by letter) from (
select 'A' as letter from dual union all
select 'Á' as letter from dual union all
select 'B' as letter from dual union all
select 'C' as letter from dual ) t;
结果字母顺序不同:
A, B, C, Á
后一种情况是简单的 Oracle 错误吗?
(我没有说任何关于 NLS 的事情。我认为这些查询应该独立于 NLS 以相同的方式工作。)
更新:
澄清: 我在同一个连接中 运行 在 SqlDeveloper 中一个接一个地查询这些查询。
NLS_SORT HUNGARIAN
NLS_COMP BINARY
(如果@MT0 的回答是解决方案,那么恕我直言,这是 oracle 中的一个错误,在简单的 order by 子句和 listagg 调用上使用不同的默认 NLS 设置。)
字母的顺序主要取决于 NLS_SORT
,所以您在邮件末尾所说的是完全错误的。
主要问题是 - 您是否在具有所有相同 NLS 设置的完全相同的系统上得到了那些相互矛盾的结果?如果是这样,那就是 LISTAGG
中 ORDER BY
子句的实现中的错误。最好有一个测试用例 - 向我们展示您的 NLS 设置(select * from v$nls_parameters
的结果),紧接着是两个查询及其输出。为了更好地衡量,还显示 select * from v$version
(告诉我们您的数据库版本)。
您需要提供 NLS_SORT
设置:
select listagg(letter,', ')
within group (order by NLSSORT(letter, 'NLS_SORT=BINARY_AI')) AS letters
from (
select 'A' as letter from dual union all
select 'Á' as letter from dual union all
select 'B' as letter from dual union all
select 'C' as letter from dual
) t;
输出:
LETTERS A, Á, B, C
注意:LISTAGG
似乎没有在其 ORDER BY
子句中使用会话 NLS_SORT
设置;但是你可以像上图那样直接传入
如果要使用会话参数(而不是特定值):
select listagg(letter,', ')
within group (
order by NLSSORT(
letter,
( SELECT 'NLS_SORT='||value
FROM NLS_SESSION_PARAMETERS
WHERE parameter = 'NLS_SORT' )
)
) AS letters
from (
select 'A' as letter from dual union all
select 'Á' as letter from dual union all
select 'B' as letter from dual union all
select 'C' as letter from dual
) t;
db<>fiddle here