【问题标题】:oracle sorts differently on simple order by and listagg's order byoracle 在简单 order by 和 listagg 的 order by 上排序不同
【发布时间】:2022-01-03 01:33:53
【问题描述】:

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 bug?

(关于 NLS,我没有说什么。我认为这些查询应该独立于 NLS 以相同的方式工作。)

更新:

澄清: 我在同一连接中的 SqlDeveloper 中一个接一个地运行这些查询。

NLS_SORT    HUNGARIAN
NLS_COMP    BINARY

(如果@MT0 的答案是解决方案,那么恕我直言,在简单的 order by 子句和 listagg 调用中使用不同的默认 NLS 设置是 oracle 中的一个错误。)

【问题讨论】:

  • edit 提出问题并附上您的 NLS 设置(特别是 NLS_SORTNLS_COMP)。

标签: oracle listagg


【解决方案1】:

您需要提供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小提琴here

【讨论】:

    【解决方案2】:

    字母的顺序主要取决于NLS_SORT,所以你在邮件末尾所说的完全错误。

    主要问题是 - 您是否在完全相同的系统上使用所有相同的 NLS 设置获得了这些矛盾的结果?如果是这样,那么这是LISTAGGORDER BY 子句的实现中的一个错误。最好有一个测试用例 - 向我们展示您的 NLS 设置(select * from v$nls_parameters 的结果),紧跟两个查询及其输出。为了更好地衡量,还请显示select * from v$version(告诉我们您的数据库版本)。

    【讨论】:

    • “您是否在完全相同的系统上获得了这些矛盾的结果,具有所有相同的 NLS 设置” - 是的,在相同的连接中,一个接一个。 “你在消息末尾所说的完全错误” - 我声称它们应该以相对于彼此相同的方式工作,所以我保留我的声明 - 当然确切的顺序取决于 NLS。跨度>
    • 这个答案更像是一个评论而不是一个解决方案。在多个数据库版本中复制 OP 的问题很简单Oracle 11gR2Oracle 18
    • @Feri - NLS 设置在三个方面相关:首先,我们需要知道结果是使用相同的 NLS 设置获得的(在帖子中没有明确说明)。其次,该错误(如果确实是一个错误)可能不会针对 NLS_SORT 的所有选择出现,而仅针对其中一些选择。第三,如果我们可以在我们自己的系统上复制异常是非常有帮助的;因为在我的系统上我没有看到你报告的相同行为,所以整个事情显然取决于 NLS_SORT,也可能取决于 Oracle 版本。
    • @MT0:“答案”部分是,“如果一切都在同一个系统上并且具有相同的设置,那么这是一个错误”。剩下的就是资格——在我的系统上我得到了相同的结果,所以它肯定不是一个普遍的错误。当然,我可以用不同的设置复制错误,但我发现使用 OP 的设置更容易(也更相关)。而且,一旦得到确认,就像您一样,这个问题完全可以通过“这是一个错误”来回答。这个问题是一个是或不是的问题。
    猜你喜欢
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多