程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了在PostgreSQL中将bytea转换为双精度大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决在postgresql中将bytea转换为双精度?

开发过程中遇到在postgresql中将bytea转换为双精度的问题如何解决?下面主要结合日常开发的经验,给出你关于在postgresql中将bytea转换为双精度的解决方法建议,希望对你解决在postgresql中将bytea转换为双精度有所启发或帮助;

好的,我找到了答案。在postgresql中,您可以使用Python编写函数。为了启用Python,您必须安装Postgresql安装所需的特定版本的Python,并将其在PATH环境变量中可用。您可以通过查看安装说明找到postgresql安装所需的Python版本。我目前在windows上使用PostgreSQL 9.6.5,它要求使用Python 3.3。我最初尝试了最新的Python 3.6,但无法正常工作。我选择了适用于windows的最新Python 3.3,即3.3.5。

安装Python之后,您可以CREATE EXTENSION plpython3u;按照https://www.POSTGResql.org/docs/current/static/plpython.html所述在数据库上执行,从而在postgresql中启用它。从那里,您可以使用Python主体编写任何函数。

对于我的具体情况,从转换byteadouble precision[]背,我写了下面的功能:

create functION bytea_to_double_array(b bytea)
    RETURNS double precision[]
    LANGUAGE 'plpython3u'
AS $BODY$
  if 'struct' in GD:
    struct = GD['struct']
  else:
    import struct
    GD['struct'] = struct

  return struct.unpack('<' + str(int(len(b) / 8)) + 'd', b)
$BODY$;

create functION double_array_to_bytea(dblarray double precision[])
    RETURNS bytea
    LANGUAGE 'plpython3u'
AS $BODY$
  if 'struct' in GD:
    struct = GD['struct']
  else:
    import struct
    GD['struct'] = struct

  # dblarray here is really a List.
  # POSTGResql passes sql arrays as Python Lists
  return struct.pack('<' + str(int(len(dblarray))) + 'd', *dblarray)
$BODY$;

在我的情况下,所有双打都存储在little endian中,因此我使用<。我还struct按照的描述,将模块的导入缓存在全局字典中。我使用GD而不是SD,因为我希望导入可以在我可能编写的其他函数中使用。有关GD和SD的信息,请参见https://www.POSTGResql.org/docs/current/static/plpython- sharing.HTML。

要了解它的作用,请知道我数据库中的blob以小字节序存储,

SELECT bytea_to_double_array(decode('efbeaddeefbeadde', 'hex')), encode(double_array_to_bytea(arraY[-1.1885959257070704E148]), 'hex');

我得到的答案是

bytea_to_double_array    | encode
double precision[]       | text
-------------------------+------------------
{-1.18859592570707e+148} | efbeaddeefbeadde

这里'efbeaddeefbeadde''deadbeefdeadbeef'在小尾数。

解决方法

我有一个数据库,其中的一个表存储bytea从另一个系统收集的各种通用数据的Blob()。该bytea字段可以包含任何内容。为了知道如何解释数据,该表还具有一个格式字段。我写了一个Java应用程序读取bytea从数据库的字段byte[],然后我可以很容易地将其转换为double[]int[]或任何格式字段表示,通过ByteBuffer与各种视图(DoubleBufferIntBuffer,等)。

现在,我需要在触发器函数中对数据库本身上的数据进行一些操作,以保持与另一个表的完整性。我可以找到几乎可以想象到的任何数据类型的转换,但是我找不到从bytea(甚至bit到)往返的任何数据double precisionbytea可以将A分解,转换为位,然后转换为intor bigint,但不能转换为a double precision。例如,x'deadbeefdeadbeef'::bit(64)::bigint将毫无问题地转换为-2401053088876216593,而是x'deadbeefdeadbeef'::bit(64)::double precision失败,并显示“错误:无法将类型位转换为双精度”,而不给出IEEE 754的答案-1.1885959257070704E148

我找到了这个答案它基本上实现了IEEE标准,可以将位转换为两倍,但是postgresql中确实没有基本的转换功能吗?另外,当我处理完数据并需要更新表时,我也需要倒退double precisionbytea直到这个答案没有提供。

最好的解决方案是使用sqL命令使用IEEE754-1985标准将其转换为字节。

首先,需要检查IEEE754-1985标准定义的特殊情况。然后,如果不是特殊情况,只需遵循标准算法进行转换。示例代码如下

bytea_value bytea,is_little_endian Boolean然后将输入分为4个字节,如下所示:

  byte_array[0]:= geT_Byte(bytea_value,0);
  byte_arraY[1]:= geT_Byte(bytea_value,1);
  byte_array[2]:= geT_Byte(bytea_value,2);
  byte_arraY[3]:= geT_Byte(bytea_value,3);

然后通过虑小端或大端获得二进制值

IF is_little_endian THEN
binary_value:= byte_array[0]::bit(8) || byte_arraY[1]::bit(8) || byte_array[2]::bit(8) || byte_arraY[3]::bit(8);
ELSE
binary_value:= byte_arraY[3]::bit(8) || byte_array[2]::bit(8) || byte_arraY[1]::bit(8) || byte_array[0]::bit(8);
END IF;
现在检查特殊情况:

IF binary_value = '00000000000000000000000000000000' OR binary_value = '10000000000000000000000000000000' THEN -- IEEE754-1985 Zero
        return 0.0;
    END IF;

sign := subString(binary_value from 1 for 1);
    exponent := subString(binary_value from 2 for 8);
    mantissa := subString(binary_value from 10 for 23); 

    IF exponent = '11111111' THEN
        IF mantissa = '00000000000000000000000' THEN   -- IEEE754-1985 negative and positive infinity
            IF sign = '1' THEN                    
                return '-Infinity';                    
            ELSE                    
                return 'Infinity';  
            END IF;                  
        ELSE
          return 'NaN'; -- IEEE754-1985 Not a number
        END IF; 
    END IF;

如果它不属于任何特殊情况,则将其转换如下:

exp := exponent::int;

    IF exp > 126 THEN
     exp := exp - 127;
    ELSE
     exp:= -exp;
    END IF;

    WHILE mantissa_index < 24 LOOP
        IF subString(mantissa from mantissa_index for 1) = '1' THEN
            result := result + power(2,-(mantissa_indeX));
        END IF;
        mantissa_index = mantissa_index + 1;
    END LOOP;

    result := result * power(2,exp);

    IF(sign = '1') THEN
        result = -result;
    END IF;

    return result;

有任何想法吗?

大佬总结

以上是大佬教程为你收集整理的在PostgreSQL中将bytea转换为双精度全部内容,希望文章能够帮你解决在PostgreSQL中将bytea转换为双精度所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。