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

Ukládání json, jsonb, hstore, xml, enum, ipaddr atd. se nezdaří, protože sloupec x je typu json, ale výraz má proměnlivý typ

Proč se to děje

Problém je v tom, že PostgreSQL je příliš striktní ohledně přetypování mezi textovými a netextovými datovými typy. Nepovolí implicitní přetypování (bez CAST nebo :: v SQL) z textového typu jako text nebo varchar (character varying ) na textový netextový typ, jako je json , xml , atd.

Ovladač PgJDBC specifikuje datový typ varchar když zavoláte setString pro přiřazení parametru. Pokud databázový typ sloupce, argument funkce atd. ve skutečnosti není varchar nebo text , ale místo jiného typu se zobrazí chyba typu. To platí také pro mnoho dalších ovladačů a ORM.

PgJDBC:stringtype=unspecified

Nejlepší možností při použití PgJDBC je obecně předat parametr stringtype=unspecified . Toto přepíše výchozí chování předávání setString hodnoty jako varchar a místo toho ponechává na databázi, aby „uhádla“ jejich datový typ. Téměř ve všech případech to dělá přesně to, co chcete, předáním řetězce do validátoru vstupu pro typ, který chcete uložit.

Vše:CREATE CAST ... WITH FUNCTION ...

Místo toho můžete CREATE CAST k definování specifického přetypování datového typu, které to umožní na základě typu po typu, ale to může mít vedlejší účinky jinde. Pokud to uděláte, nedělejte to použijte WITHOUT FUNCTION přetypování, obejdou ověření typu a způsobí chyby. Pro datový typ musíte použít funkci input/validation. Pomocí CREATE CAST je vhodný pro uživatele jiných databázových ovladačů, kteří nemají žádný způsob, jak zastavit ovladač specifikující typ pro řetězcové/textové parametry.

např.

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;

Vše:Obslužný program vlastního typu

Pokud to vaše ORM dovoluje, můžete implementovat vlastní popisovač typu pro datový typ a konkrétní ORM. To je většinou užitečné, když používáte nativní typ Java, který se dobře mapuje na typ PostgreSQL, místo použití String , i když to může také fungovat, pokud vám váš ORM umožňuje specifikovat obslužné rutiny typu pomocí anotací atd.

Metody implementace obslužných rutin vlastního typu jsou specifické pro ovladač, jazyk a ORM. Zde je příklad pro Java a Hibernate pro json .

PgJDBC:zadejte obslužný program pomocí PGObject

Pokud v Javě používáte nativní typ Java, můžete rozšířit PGObject poskytnout mapování typu PgJDBC pro váš typ. Pravděpodobně budete také muset implementovat obslužný program typu specifický pro ORM, abyste mohli používat váš PGObject , protože většina ORM bude volat pouze toString na typy, které neznají. Toto je preferovaný způsob mapování komplexních typů mezi Java a PostgreSQL, ale také nejsložitější.

PgJDBC:Zadejte obslužný program pomocí setObject(int, Object)

Pokud používáte String pro uchování hodnoty v Javě, místo specifičtějšího typu, můžete vyvolat metodu JDBC setObject(integer, Object) pro uložení řetězce bez zadaného konkrétního datového typu. Ovladač JDBC odešle reprezentaci řetězce a databáze odvodí typ z typu cílového sloupce nebo typu argumentu funkce.

Viz také

Otázky:

  • Mapování sloupce postgreSQL JSON na typ hodnoty Hibernate
  • Jsou možné vlastní typy JPA (EclipseLink)?

Externí:

  • 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. Jak lze dočasně deaktivovat omezení cizích klíčů pomocí T-SQL?

  2. Vyberte velikost databáze SQL Server

  3. 7645 Nula nebo prázdný fulltextový predikát

  4. Jak získat jméno krátkého dne z data v MariaDB