sql >> Databáze >  >> RDS >> PostgreSQL

Převeďte byte na dvojnásobnou přesnost v PostgreSQL

Ok, našel jsem odpověď. V PostgreSQL můžete psát funkce pomocí Pythonu. Abyste mohli používat Python, musíte nainstalovat konkrétní verzi Pythonu potřebnou pro vaši instalaci PostgreSQL a mít ji k dispozici v proměnné prostředí PATH. Jakou verzi Pythonu vaše instalace PostgreSQL potřebuje, zjistíte v poznámkách k instalaci. V současné době používám PostgreSQL 9.6.5 na Windows a vyžaduje Python 3.3. Původně jsem zkoušel nejnovější Python 3.6, ale nefungovalo to. Spokojil jsem se s nejnovějším Pythonem 3.3 pro Windows, což je 3.3.5.

Po instalaci Pythonu jej povolíte v PostgreSQL spuštěním CREATE EXTENSION plpython3u; ve vaší databázi, jak je zdokumentováno zde https://www.postgresql.org/docs /current/static/plpython.html . Odtud můžete psát libovolnou funkci s těly Pythonu.

Pro můj konkrétní případ převod z bytea na double precision[] a zpět jsem napsal následující funkce:

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$;

V mém případě jsou všechny dvojky uloženy v little endian, takže používám < . Také ukládám do mezipaměti import struct modulu v globálním slovníku, jak je popsáno v https://stackoverflow.com/a/15025425/5274457 . Použil jsem GD místo SD, protože chci, aby byl import dostupný v jiných funkcích, které mohu psát. Informace o GD a SD najdete na https://www.postgresql .org/docs/current/static/plpython-sharing.html .

Abych to viděl v akci, když vím, že bloby v mé databázi jsou uloženy jako little endian,

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

A odpověď, kterou dostávám, je

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

kde 'efbeaddeefbeadde' je 'deadbeefdeadbeef' v little endian.




  1. Identifikujte telefonní čísla v iteraci PL/SQL

  2. Vracení záznamů za poslední 3 měsíce pouze v MySQL

  3. Odstranit ze dvou tabulek v jednom dotazu

  4. Odstraňte duplicitní výsledky ve výběrovém dotazu, který obsahuje sloupec CLOB