bytea类型&无效,Postgres

时间:2010-06-07 17:45:53

标签: postgresql

我在PostgreSQL中使用bytea类型,根据我的理解,它只包含一系列字节。但是,我无法让它与nulls一起发挥。例如:

=# select length(E'aa\x00aa'::bytea);
 length
--------
      2
(1 row)

我期待着5.另外:

=# select md5(E'aa\x00aa'::bytea);
               md5
----------------------------------
 4124bc0a9335c27f086f24ba207a4912
(1 row)

这是“aa”的MD5,而不是“aa \ x00aa”。显然,我做错了,但我不知道我做错了什么。由于我无法控制的原因,我也使用旧版本的Postgres(8.1.11)。 (一旦我回到家,我会看到最新Postgres的表现是否相同......)

2 个答案:

答案 0 :(得分:9)

试试这个:

# select length(E'aa\\000aa'::bytea);
 length
--------
      5

更新:为什么原版不起作用?首先,了解一个斜杠和两个斜杠之间的区别:

pg=# select E'aa\055aa', length(E'aa\055aa') ;
 ?column? | length
----------+--------
 aa-aa    |      5
(1 row)

pg=# select E'aa\\055aa', length(E'aa\\055aa') ;
 ?column? | length
----------+--------
 aa\055aa |      8

在第一种情况下,我正在写一个文字字符串,4个字符未转义('a')和一个转义。解析器在第一遍中使用斜杠,转换完整的\055  到一个字符(在这种情况下为' - ')。

在第二种情况下,第一个斜杠只是逃避第二个斜杠,对\\由解析器转换为单个\055被视为三个字符。< / p>

现在,在将文本转换为bytea时,转义字符(在已经解析或生成的文本中)被解析/解释again! (是的,这很令人困惑)。

所以,当我写

 select E'aa\000aa'::bytea;

在第一次解析时,文字E'aa \ 000aa'被转换为第三个位置带有空字符的内部文本(根据你的postgresql版本,空字符被解释为EOS,文本假设长度为2 - 或者在其他版本中抛出非法字符串错误。

相反,当我写

 select E'aa\\000aa'::bytea;

在第一次解析中,看到文字字符串“aa \ 000aa”(八个字符),并且与文本对齐;然后在转换为bytea时,它再次被解析,并且字符序列'\ 000'被解释为空字节。

IMO postgresql在这里很糟糕。

答案 1 :(得分:0)

您可以使用常规字符串或带引号的字符串代替转义的字符串:

# select length('aa\000aa'::bytea);
 length 
════════
      5
(1 row)

# select length($$aa\000aa$$::bytea);
length 
════════
      5
(1 row)

我认为用美元报价的字符串是一个更好的选择,因为如果配置参数standard_conforming_strings关闭,则PostgreSQL可以在常规字符串常量和转义字符串常量中识别反斜杠转义。但是,从PostgreSQL 9.1开始,默认设置为on,这意味着反斜杠转义只能在转义字符串常量中识别。