【问题标题】:How can I sort by a table column in varying cases (Oracle)如何在不同情况下按表列排序(Oracle)
【发布时间】:2012-04-05 00:58:02
【问题描述】:

如何对包含不同大小写字符(UPPERlower)的 varchar2 列的表进行排序?

例如,当我对 Name 列进行排序时,我得到以下结果:

ANNIE
BOB
Daniel
annie
bob

我想要的是这样的:

ANNIE
annie
BOB
bob
Daniel

【问题讨论】:

    标签: sql oracle select sql-order-by case-sensitive


    【解决方案1】:

    使用lower(field),例如

    select * from tbl order by lower(name)
    

    如果您需要解决非英语语言的特殊字符,那么有关 NLSSORT 的其他答案可能就是您所需要的。如果你不这样做,我会尝试亲吻并使用lower(),因为它很容易记住、使用和被其他人阅读(可维护性)。

    【讨论】:

    • 要补充的一点是,这意味着除非lower(name) 上有功能索引,否则将使用此查询完成全表扫描。
    • 这个查询总是需要全表扫描,不管有没有 ORDER BY。通常,您所描述的问题对于 WHERE 子句更为重要。
    • @DCookie:你要赌吗? ;) 例如尝试在 lower(name) 上添加功能索引,并附加表中的所有列 = 全索引扫描,加上不排序:) - 只是说'
    • 不要迂腐,但UPPER() 将是规范的、教科书式的做法。如果基于函数的索引存在或将存在,您更有可能在UPPER() 上找到它而不是LOWER()
    【解决方案2】:

    另一种选择是使用NLSSORT 函数来执行linguistic sorting

    SQL> with test as (select 'ANNIE' as col from dual
      2      union all select 'BOB' from dual
      3      union all select 'Daniel' from dual
      4      union all select 'annie' from dual
      5      union all select 'bob' from dual
      6      union all select 'Ångström' from dual
      7      union all select 'ångström' from dual)
      8  select col
      9  from test
     10  order by nlssort(col, 'NLS_SORT = WEST_EUROPEAN')
     11  /
    
    COL
    ----------
    Ångström
    ångström
    ANNIE
    annie
    BOB
    bob
    Daniel
    

    优点是更灵活。可以将带有重音符号的字符以及不同的大小写一起排序。可以通过specifying different values for NLS_SORT 选择以特定语言的方式处理某些字符。定义等效字符集中的顺序。所以 'A' 和 'a' 被排序在一起,但在 'a's 中,大写字母在前。缺点我预计 NLSSORT 使用的 CPU 比 LOWER 多,尽管我没有对其进行基准测试。而 NLSSORT 只会使用 longer strings 的前缀:

    返回的字符串,也称为排序规则,是 RAW 数据 类型。给定 char 产生的排序规则键的长度 给定排序规则的值可能超过 2000 字节,即 NLSSORT 返回的 RAW 值的最大长度。在这种情况下, NLSSORT 计算最大前缀或初始值的排序规则键 substring, char 以便计算结果不超过 2000 字节。对于单语排序规则,例如 FRENCH,前缀 长度通常为 1000 个字符。对于多语言排序规则,对于 例如 GENERIC_M,前缀通常为 500 个字符。最正确 长度可能会更低或更高,具体取决于排序规则和 char 中包含的字符。

    【讨论】:

    【解决方案3】:

    如果您使用的是相对较新的 Oracle 版本,则应考虑设置 NLS_SORT/NLS_COMP,而不是使用 LOWER() 函数。

    如果您不想全局影响实例,可以使用 NLSSORT() 函数为特定查询的范围设置 NLS_SORT。

    SQL> create table case_insensitive(a varchar2(10));
    
    Table created.
    
    SQL> insert into case_insensitive values('D');
    
    1 row created.
    
    SQL> 
    SQL> 
    SQL> c/'D/'c
      1* insert into case_insensitive values('c')
    SQL> /
    
    1 row created.
    
    SQL> c/'c/'B
      1* insert into case_insensitive values('B')
    SQL> /
    
    1 row created.
    
    SQL> c/'B/'a
      1* insert into case_insensitive values('a')
    SQL> /
    
    1 row created.
    
    SQL> commit;
    
    Commit complete.
    
    SQL> select * from case_insensitive;
    
    A
    ----------
    D
    c
    B
    a
    
    SQL> select * from case_insensitive order by a;
    
    A
    ----------
    B
    D
    a
    c
    
    SQL> select * from case_insensitive order by nlssort(a,'NLS_SORT=BINARY_CI'); 
    
    A
    ----------
    a
    B
    c
    D
    

    可以在here.找到一个很好的例子

    【讨论】:

    • 设置 NLS_SORT/NLS_COMP 将改变所有查询的行为。如果这是一个人想要的,那就太好了。如果不是这样就不是很好。
    • 不一定。我将返回并编辑我的示例以进行演示。
    • NLSSORT 和 NLS_SORT 都是由 Oracle 定义的,但它们是不同的东西。这个答案的顶部引用了 NLS_SORT,一个参数。但是,在我评论后添加的代码使用 NLSSORT 函数。因此,如果您最初的意思是 NLSSORT,那么您是正确的,我的评论不适用。 NLSSORT docs.oracle.com/cd/E11882_01/server.112/e26088/…, NLS_SORT docs.oracle.com/cd/E11882_01/server.112/e25513/…
    • 我链接到的文章涵盖了两者。如果你不喜欢我的回答,你可以投反对票。
    【解决方案4】:

    您可以使用INITCAP,例如

    SELECT fld FROM tbl ORDER BY INITCAP(fld) ASC;
    

    【讨论】:

    • 没有理由提供不比公认答案更好的答案。此外,initcap 不会做(考虑 'ANNA' 和 'annie')。
    【解决方案5】:

    您可以为此使用 Order by cluse

    select col_name from table_name 
    order by col_name ;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-15
      • 1970-01-01
      • 2012-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-15
      相关资源
      最近更新 更多