sql - 如何将类型 bytea 转换为 double

标签 sql postgresql

我有一个类型为 bytea 的数据库列。它包含转换为字节数组的 float (每个 float 4 个字节)并且编码为 Escape。我能够使用 substring 函数检索相应的 bytea 字符串。

我的问题是如何在 SQL 函数中将 bytea 字符串转换为 float 。早些时候我在 C# 端转换为 float。我使用 dataReader.getByte 方法检索字节,然后使用 BitConverter.ToSingle(.Net 类中构建)方法转换为 float 。

现在我不能使用中间组件作为 Npqsql 驱动程序。我希望 SQL 在从第 3 方应用程序执行查询时直接将 bytea 转换为 float 并返回相应的数字。

谢谢 阿米拉

最佳答案

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

首先需要检查 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;

关于sql - 如何将类型 bytea 转换为 double ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9374561/

相关文章:

postgresql - 改变 pg_config

postgresql - 为什么即使对象创建失败,Postgres 序列项也会上升?

json - Postgres 对 json 字段的全文搜索

mysql - Concat 连接的结果

sql - 在 wamp 中运行 8mb 的 sql 代码?

Delphi ADO 内存消耗

sql - 使用 SELECT 语句查询自定义 postgresql 参数

php - sql 计算来自特定字段的唯一值

3表内连接的SQL计算

具有不同列的两个表的 SQL 并集