为什么 '2' > '10'?

20
为什么带有初始空格的 '2' 比 '10' 大?
select ' 2' > '10';
 ?column? 
----------
 t
(1 row)

我尝试使用了latin1和utf8英语排序:

                                    List of databases
   Name    |   Owner    | Encoding  |    Collation     |      Ctype       |   Access privileges   
-----------+------------+-----------+------------------+------------------+-----------------------
 cpn       | cpn        | UTF8      | en_US.UTF-8      | en_US.UTF-8      | 
 teste     | cpn        | LATIN1    | en_US.ISO-8859-1 | en_US.ISO-8859-1 | 

我知道这与类型有关,因为当进行强制类型转换时,它的表现符合预期:

teste=> select ' 2'::char > '10';
 ?column? 
----------
 f
(1 row)

这里到底发生了什么?
编辑:
以上所有内容都是在Fedora 13中使用8.4.8完成的。但我刚刚在Centos 6中使用9.04进行了测试,结果相同。
select ' 2' > '10';
 ?column? 
----------
 t
(1 row)

数据库列表

   Name    |   Owner    | Encoding  |  Collation  |    Ctype    |   Access privileges   
-----------+------------+-----------+-------------+-------------+-----------------------
 cpn       | postgres   | UTF8      | en_US.UTF-8 | en_US.UTF-8 | 

新编辑:
这是为了进一步混淆:
select ' ' > '1';
 ?column? 
----------
 f
(1 row)

你正在使用哪个版本的PostgreSQL? - Vincent Savard
@Jared 如果我去掉空格,那么它会按预期工作,也就是说,“2”比“10”大。 - Clodoaldo Neto
8
请先阅读答案再投票。 - Stéphane Gimenez
5
这个讨论串支持“所有UTF-8排序规则都会忽略空格”的说法(链接在这里)。还有其他类似的串,因此问题似乎在于这些排序规则中空格被忽略了。 - Dan Grossman
@ypercube 我无法测试答案,我无法接触到Postgres安装。如果您想发布答案,请随意使用该链接。 - Dan Grossman
显示剩余9条评论
2个回答

5
我认为PostgreSQL会在幕后自动尝试确定类型,在Linux中它会尝试去掉' ',一些比较也基于语言环境。
因此,' 2' > '10' 变成了 '2'>'10',比较结果是 '2'>'1';它们不相等,所以没有必要继续比较字符串的其余部分,而且 ascii('2') 大于 ascii('1'),所以结果为真。
如果是等式操作(例如 ' 22' = '22 '),则结果为假,因为Postgres进行逐字节比较。这很重要,因为引擎在进行比较时使用了两种不同的算法。
如果您通过类型转换指定类型,则不会覆盖空格规则(' '=>'')。
同时感谢RhodiumToad和Peerce在#postgresql中的贡献。

3
我认为这与本地设置有关。
根据PostgreSQL文档:Locale Support
区域设置会影响以下SQL功能:
  • 使用ORDER BY对文本数据进行排序的查询
  • 使用LIKE子句使用索引的能力
  • upper,lower和initcap函数
  • to_char函数家族

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接