sql >> Databasteknik >  >> RDS >> PostgreSQL

Att lagra json, jsonb, hstore, xml, enum, ipaddr, etc misslyckas med kolumn x är av typen json men uttrycket är av typen som varierar

Varför det händer

Problemet är att PostgreSQL är alltför strikt när det gäller casts mellan text- och icke-textdatatyper. Den tillåter inte en implicit cast (en utan en CAST). eller :: i SQL) från en texttyp som text eller varchar (character varying ) till en textliknande icke-texttyp som json , xml , etc.

PgJDBC-drivrutinen anger datatypen för varchar när du anropar setString för att tilldela en parameter. Om databastypen för kolumnen, funktionsargument, etc, faktiskt inte är varchar eller text , men istället en annan typ får du ett typfel. Detta gäller även för en hel del andra förare och ORM.

PgJDBC:stringtype=unspecified

Det bästa alternativet när du använder PgJDBC är i allmänhet att skicka parametern stringtype=unspecified . Detta åsidosätter standardbeteendet för att skicka setString värden som varchar och istället överlåter det till databasen att "gissa" deras datatyp. I nästan alla fall gör detta precis vad du vill, och skickar strängen till indatavalidatorn för den typ du vill lagra.

Alla:CREATE CAST ... WITH FUNCTION ...

Du kan istället CREATE CAST att definiera en datatypspecifik cast för att tillåta detta på typ-för-typ-basis, men detta kan ha biverkningar på andra ställen. Om du gör detta, gör inte använd WITHOUT FUNCTION casts kommer de att kringgå typvalidering och resultera i fel. Du måste använda inmatnings-/valideringsfunktionen för datatypen. Använder CREATE CAST är lämplig för användare av andra databasdrivrutiner som inte har något sätt att stoppa drivrutinen som anger typen för sträng-/textparametrar.

t.ex.

CREATE OR REPLACE FUNCTION json_intext(text) RETURNS json AS $$
SELECT json_in($1::cstring); 
$$ LANGUAGE SQL IMMUTABLE;

CREATE CAST (text AS json) 
WITH FUNCTION json_intext(text) AS IMPLICIT;

Alla:Anpassad typhanterare

Om din ORM tillåter kan du implementera en anpassad typhanterare för datatypen och den specifika ORM. Detta är mest användbart när du använder inbyggd Java-typ som mappar väl till PostgreSQL-typen, snarare än att använda String , men det kan också fungera om din ORM låter dig specificera typhanterare med anteckningar etc.

Metoder för att implementera anpassade typhanterare är drivrutins-, språk- och ORM-specifika. Här är ett exempel för Java och Hibernate för json .

PgJDBC:skriv hanterare med PGObject

Om du använder en inbyggd Java-typ i Java kan du utöka PGObject för att tillhandahålla en PgJDBC-typmappning för din typ. Du kommer förmodligen också att behöva implementera en ORM-specifik typhanterare för att använda ditt PGObject , eftersom de flesta ORM:er bara anropar toString på typer som de inte känner igen. Detta är det föredragna sättet att mappa komplexa typer mellan Java och PostgreSQL, men också det mest komplexa.

PgJDBC:Typhanterare med setObject(int, Object)

Om du använder String för att hålla värdet i Java, snarare än en mer specifik typ, kan du anropa JDBC-metoden setObject(integer, Object) för att lagra strängen utan någon speciell datatyp specificerad. JDBC-drivrutinen skickar strängrepresentationen, och databasen kommer att sluta sig till typen från destinationskolumntypen eller funktionsargumenttypen.

Se även

Frågor:

  • Mappa postgreSQL JSON-kolumn till Hibernate-värdetyp
  • Är JPA (EclipseLink) anpassade typer möjliga?

Externt:

  • http://www.postgresql.org/message-id/[email protected]
  • https://github.com/pgjdbc/pgjdbc/issues/265
  • http://www.pateldenish.com/2013/05/inserting-json-data-into-postgres-using-jdbc-driver.html



  1. SQL UPPDATERING för nybörjare

  2. ORA-00904:ogiltig identifierare

  3. Returnera kortdagens namn från ett datum i Oracle

  4. Grunderna i sys.dm_exec_requests