web-dev-qa-db-fra.com

Insérer une chaîne de texte hex avec PostgreSQL sous forme de bytea

J'ai un fichier texte avec plusieurs chaînes d'hex:

013d7d16d7ad4fefb61bd95b765c8ceb
007687fc64b746569616414b78c81ef1

Je voudrais les stocker dans la base de données en tant que bytea , au lieu de varchar . C'est-à-dire que j'aimerais que la base de données stocke 01 sous le seul octet 00000001, et non les caractères "0" et "1".

Je peux facilement exécuter ce fichier via sed pour le formater/l’échapper par tous les moyens.

C'est ce que j'ai essayé:

create table mytable (testcol BYTEA);

Cela marche:

insert into mytable (testcol) values (E'\x7f\x7f');

Cependant, dès que j'ai un octet supérieur à\x7f, j'obtiens cette erreur:

insert into mytable (testcol) values (E'\x7f\x80');
ERROR:  invalid byte sequence for encoding "UTF8": 0x80

Des idées, ou est-ce que j'aborde les choses mal?

38
Donald Miner

Vous pouvez convertir une chaîne hexadécimale en octets en utilisant la fonction decode (où "encoding" signifie coder une valeur binaire en une valeur textuelle). Par exemple:

select decode('DEADBEEF', 'hex');
      decode      
------------------
 \336\255\276\357

ce qui est plus compréhensible avec la sortie par défaut de la 9.0:

   decode   
------------
 \xdeadbeef

La raison pour laquelle vous ne pouvez pas simplement dire E'\xDE\xAD\xBE\xEF' est que cela est destiné à créer une valeur textuelle, pas un bytea, donc Postgresql essaiera de la convertir du codage client en codage de base de données. Vous pouvez écrire le format d'échappement bytea de cette manière, mais vous devez doubler les barres obliques inverses: E'\\336\\255\\276\\357'::bytea. Je pense que vous pouvez voir pourquoi le format bytea est en train d'être modifié ... IMHO, la fonction decode() est un moyen raisonnable d'écrire des entrées, même s'il y a une surcharge.

64
araqnid
INSÉRER DANS
 mytable (testcol) 
 VALEURS 
 (décode ('013d7d16d7ad4fefb61bd95b765c8ceb', 'hex')) 
22
Julius Musseau

La manière rubis

J'ai récemment eu besoin de lire/écrire des données binaires de/vers Postgres, mais via Ruby. Voici comment je l'ai fait en utilisant la bibliothèque Pg .

Bien que n'étant pas strictement spécifique à Postgres, je pensais inclure cette réponse centrée sur Ruby à titre de référence.

Configuration de la base de données Postgres

require 'pg'
DB = PG::Connection.new(Host: 'localhost', dbname:'test')
DB.exec "CREATE TABLE mytable (testcol BYTEA)"
BINARY = 1

Insérer des données binaires

sql = "INSERT INTO mytable (testcol) VALUES ($1)"
param = {value: binary_data, format: BINARY}
DB.exec_params(sql, [param]) {|res| res.cmd_tuples == 1 }

Sélectionner des données binaires

sql = "SELECT testcol FROM mytable LIMIT 1"
DB.exec_params(sql, [], BINARY) {|res| res.getvalue(0,0) }
5
Clint Pachl

Plus et divers options :

-- insert 123[char of value zero]abc456
insert into mytable (testcol) values decode(E'123\\000abc456', 'escape');

-- insert abc456
insert into mytable (testcol) values decode('YWJjNDU2', 'base64');
0
rogerdpack