代码之家  ›  专栏  ›  技术社区  ›  Thanatos

字节类型和空值,Postgres

  •  2
  • Thanatos  · 技术社区  · 14 年前

    我用的是 bytea 键入postgresql,据我所知,它只包含一系列字节。但是,我不能让它和空值玩得很好。例如:

    =# 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 回复  |  直到 5 年前
        1
  •  9
  •   leonbloy    14 年前

    试试这个:

    # 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 被视为三个字符。

    现在,当将文本转换为字节时,转义字符(在已经解析或生成的文本中)将被解析/解释。 again !(是的,这很混乱)。

    所以,当我写作的时候

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

    在第一个解析中,文本e'a a\000a a'转换为第三个位置具有空字符的内部文本(根据您的PostgreSQL版本,空字符被解释为EOS,并且假定文本的长度为2,或者在其他版本中引发非法字符串错误)。

    相反,当我写作时

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

    在第一次解析中,会看到文本字符串“a a\000a a”(8个字符),并将其指定为文本;然后在转换为byte a时,会再次对其进行解析,并将字符序列'\000'解释为空字节。

    我觉得PostgreSQL有点糟糕。

        2
  •  0
  •   Marcello Nuccio    5 年前

    您可以使用常规字符串或美元引号字符串,而不是转义字符串:

    # 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,这意味着反斜杠转义只能在转义字符串常量中识别。