Postgres中字符串包含特定符号字符时的神秘比较结果

3

当我尝试比较包含斜杠“/”或问号“?”的字符串时,我的Postgres服务器给我非常令人困惑的结果。例如,在psql中运行以下命令:

select ('/' < '1') as c1,
       ('/1' < '1') as c2,
       ('/////1' < '1') as c3,
       ('/1' < '2') as c4,
       ('/1' < '11') as c5;

结果如下:
 c1 | c2 | c3 | c4 | c5
----+----+----+----+----
 t  | f  | f  | t  | t

'/''1'小,但是'/1''1'大。实际上,'/1''1''2'之间,'/////1'也是如此。这不遵循字典顺序。

然而,'/1'(正确地)比11小,这让我更加困惑。

我想知道'/1'是否被视为已转义。所以我运行了:

select length('/1');

我得到了2,这意味着postgres将'/1'视为两个字符的字符串。

当我用其他符号如$?替换/时,同样的问题会发生。

如果您有docker,可以通过在docker容器中运行postgres轻松地重现此问题:

docker run postgres:11
docker exec  -it `docker ps | grep postgres:11 | cut -d' ' -f 1` psql -U postgres

然后尝试上面的SQL。我尝试了postgres 10映像,行为是相同的。当我将VARCHAR列与字符串文字进行比较时,真实的SQL会发生同样的事情。这个问题让我疯狂,因为我需要写正确的SQL来比较文件路径,而文件路径显然包含许多“/”符号。我搜索了一下,并没有找到任何关于这个问题的文档,所以这看起来不像是postgres的“官方特性”。什么是编写遵循词典顺序比较的正确方法?非常感谢。
1个回答

2
Postgres使用操作系统的排序规则(在Linux上,这将是由glibc提供的规则)。因此,您的结果取决于底层操作系统。 您可以通过使用"C"排序规则来强制进行ASCCI比较(如上例所示):
select '/1' > '1' collate "C"

这似乎在所有平台上都可以使用相同的方式。或者您可以指定一个ICU排序规则,这也可以在所有平台上以相同的方式工作。
您提到您想比较文件路径。仅比较“名称”(忽略分隔符)的一种方法是将路径转换为数组string_to_array(filepath, '/'),然后例如使用该数组进行排序或比较。

哦!你是救命恩人!谢谢你! - Zhan Su

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