2013-07-28 19 views
11

Ora uso di analizzare manualmente JSON in stringa inserto in questo modoPostgreSQL: inserire i dati nella tabella da JSON

insert into Table (field1, field2) values (val1, val2) 

ma il suo modo non è comodo per inserire i dati da JSON! ho trovato la funzione json_populate_record e provato ad usarlo:

create table test (id serial, name varchar(50)); 
insert into test select * from json_populate_record(NULL::test, '{"name": "John"}'); 

ma riesce con il messaggio: valore nullo nella colonna "id" viola vincolo not-null PG sa che id è seriale, ma finge di essere un pazzo. Lo stesso vale per tutti gli spegni con valori predefiniti.

Esiste un codice più elegante per inserire dati da json in una tabella?

+1

"Ho trovato la funzione' json_populate_record' ". Um. *Dove*? Qual è la definizione della funzione? Stai usando PostgreSQL 9.3 beta, o è una funzione che hai installato da qualche altra parte? –

+0

It's 9.3 beta's function – user2627000

risposta

10

Non esiste un modo semplice per json_populate_record per restituire un indicatore che significa "generare questo valore".

PostgreSQL fa non consente di inserire NULL per specificare che un valore deve essere generato. Se si chiede NULL Pg si aspetta mediaNULL e non si vuole indovinare. Inoltre è perfettamente OK avere una colonna generata che non ha il vincolo NOT NULL, nel qual caso è perfettamente adatto inserire NULL in esso.

Se si desidera avere PostgreSQL utilizzare il default tavolo per un valore ci sono due modi per farlo:

  • Omettere quella riga dal INSERT colonna-list; o
  • esplicitamente scrivere DEFAULT, che è valido solo in un'espressione VALUES

Dal momento che non è possibile utilizzare VALUES(DEFAULT, ...) qui, l'unica opzione è quella di omettere la colonna dalla colonna INSERT-list:

regress=# create table test (id serial primary key, name varchar(50)); 
CREATE TABLE 
regress=# insert into test(name) select name from json_populate_record(NULL::test, '{"name": "John"}'); 
INSERT 0 1 

Sì, questo significa che è necessario elencare le colonne. Due volte, infatti, una volta nell'elenco di SELECT e una volta nell'elenco di colonne INSERT.

Per evitare la necessità che tale PostgreSQL avrebbe bisogno di avere un modo per specificare DEFAULT come valore per un record, quindi json_populate_record potrebbe ritornare DEFAULT anziché NULL per colonne non definiti. Potrebbe non essere quello che intendevi per tutte le colonne e porterebbe alla domanda su comeè stato json_populate_record non utilizzato in un'espressione INSERT.

Quindi penso che json_populate_record potrebbe essere meno utile di quanto speravate per le righe con le chiavi generate.

+0

very cool. c'è un modo per 'AGGIORNARE' troppo, basato su un input JSON? – jney

+0

@jney Non sono proprio sicuro di cosa stai chiedendo. Suggerisco di postare una nuova domanda correttamente dettagliata e il collegamento a questo per il contesto. –

+0

Informazioni molto utili (la documentazione per 'json_populate_record' è un po 'scarsa). Ma sembra davvero che ci sia un buon caso per un'opzione all'effetto di "dove non è specificato alcun valore, usa l'impostazione predefinita". – beldaz

6

Proseguendo da Craig's answer, probabilmente bisogno di scrivere una sorta di stored procedure per eseguire la necessaria SQL dinamico, come la seguente:

CREATE OR REPLACE FUNCTION jsoninsert(relname text, reljson text) 
    RETURNS record AS 
$BODY$DECLARE 
ret RECORD; 
inputstring text; 
BEGIN 
    SELECT string_agg(quote_ident(key),',') INTO inputstring 
    FROM json_object_keys(reljson::json) AS X (key); 
    EXECUTE 'INSERT INTO '|| quote_ident(relname) 
    || '(' || inputstring || ') SELECT ' || inputstring 
    || ' FROM json_populate_record(NULL::' || quote_ident(relname) || ' , json_in($1)) RETURNING *' 
    INTO ret USING reljson::cstring; 
    RETURN ret; 
END; 
$BODY$ 
LANGUAGE plpgsql VOLATILE; 

che hai poi chiamata con

SELECT jsoninsert('test', '{"name": "John"}'); 
Problemi correlati