Postgres摘要()与字符串concat和bytea concat的行为不同?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Postgres摘要()与字符串concat和bytea concat的行为不同?相关的知识,希望对你有一定的参考价值。

我正在尝试将一些使用pgcrypto摘要函数的postgres代码复制到Java中。我假设以下两个命令将产生相同的结果:

select digest('Hi there' || 'Abc' || decode('00','hex'), 'sha256');
select digest('Hi thereAbc' || decode('00','hex'), 'sha256');

但是,不是这样。这两个命令产生不同的结果:

postgres=# select digest('Hi there' || 'Abc' || decode('00','hex'), 'sha256');
                           digest                               
--------------------------------------------------------------------
 \xd4321124595112a1e8cd8d90709b8cf58aabdd14ad09ff972e6fe0f75bd25d97

postgres=# select digest('Hi thereAbc' || decode('00','hex'), 'sha256');
                           digest                               
--------------------------------------------------------------------
 \xf2477e4fcaf6ea37ab985fc1fa029a99fb331657e7a3e349ffc844e9d068f250

知道为什么这些结果会有所不同吗?

另一方面,在没有结尾的字节的情况下进行连接可以按预期工作:

postgres=# select digest('Hi thereAbc', 'sha256');
                          digest                              
------------------------------------------------------------------
 \x3e1d7fed02b93824aba03835b93314f0293026276c8e50f4b70935f988e0c0bf

postgres=# select digest('Hi there' || 'Abc', 'sha256');
                          digest                              
------------------------------------------------------------------
 \x3e1d7fed02b93824aba03835b93314f0293026276c8e50f4b70935f988e0c0bf

(1行)

谢谢!

编辑:答案更新根据@ferhat elmas的回答,摘要的两个输入如下:

select 'Hi thereAbc' || decode('00', 'hex');
 \x486920746865726541626300

select 'Hi there' || 'Abc' || decode('00', 'hex');
Hi thereAbc\x00

[我假设这两个值是相等的-一个作为字节,另一个作为字符串,但它们不是-反斜杠x 0 0是字符串中的文字字符,而不是单个0字节。

答案

这是因为postgres如何解析未知类型。

select 'Hi there' || 'Abc' || decode('00', 'hex')
       unknown || unknown || bytea -- see the snippet below from the docs
       string || bytea
       string

来自docs

在这种情况下,由于没有在查询中指定任何类型,因此没有使用哪种类型的初始提示。因此,解析器将查找所有候选运算符,并发现存在同时接受字符串类别和位字​​符串类别输入的候选者。由于首选字符串类别(如果可用),因此选择该类别,然后将字符串的首选类型(文本)用作特定类型,以将未知类型的文字解析为。

select 'Hi thereAbc' || decode('00', 'hex')
       unknown || bytea -- this step is hinted by the known type
       string

这就是为什么在一种情况下,文本被编码为十六进制然后进行连接的原因,而在另一种情况下,由于一种情况具有已知的类型而另一种情况不是已知的类型,因此将它们直接进行连接。

为了确保一致性,最好提供类型提示。

以上是关于Postgres摘要()与字符串concat和bytea concat的行为不同?的主要内容,如果未能解决你的问题,请参考以下文章

Postgres - 使用 CTE 的 id 列的唯一值,与 GROUP BY 一起加入

SQL Server 2012 中的 group_concat 与 ORDER BY 另一列

sparql 选择 wikidata group_by 和 concat

如何在 laravel 中使用 concat 和 group by?

group_concat sqlite 和 order by

GROUP BY 和 GROUP_CONCAT的使用