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

Jak uniknout znaku otazníku (?) pomocí Spring JpaRepository

V případě escapování ? není možné, můžete vytvořit duplicitní operátor s jiným názvem.

Nový operátor

Syntaxe pro vytváření operátorů v Postgres:

CREATE OPERATOR name (
    PROCEDURE = function_name
    [, LEFTARG = left_type ] [, RIGHTARG = right_type ]
    [, COMMUTATOR = com_op ] [, NEGATOR = neg_op ]
    [, RESTRICT = res_proc ] [, JOIN = join_proc ]
    [, HASHES ] [, MERGES ]
)

V případě ?| používá se v jsonb bude to:

CREATE OPERATOR ^|(
  PROCEDURE = jsonb_exists_any,
  LEFTARG = jsonb,
  RIGHTARG = _text,
  RESTRICT = contsel,
  JOIN = contjoinsel);

Použil jsem ^| jako příklad alternativní název. Může to být libovolná sekvence z tohoto seznamu:+ - * / < > = ~ ! @ # % ^ & | ?`.

Aktuální definici operátora, který vás zajímá, můžete najít dotazem na tabulku pg_catalog.pg_operator.

SELECT oid, *
  FROM pg_catalog.pg_operator
 WHERE oprname = '?|'
   AND oprleft = (SELECT oid FROM pg_type WHERE typname = 'jsonb');

Můžete také použít nástroj GUI jako pgAdmin a procházet pg_catalog aby byla definice SQL připravena k opětovnému použití.

Povolení indexu

Pokud chcete použít index pro tento "nový" operátor, budete muset vytvořit novou třídu operátorů a volitelně rodinu. V našem případě potřebujeme obojí, protože je nemůžeme přidat do stávající rodiny, protože výchozí operátor již zabírá strategický slot.

Stejně jako u operátorů se doporučuje použít nástroj GUI, jako je pgAdmin, k procházení tříd operátorů a pouze je zkopírovat a vložit.

Nejprve vezmeme OID operátora, jehož duplikát jsme vytvořili:

SELECT oid, *
  FROM pg_catalog.pg_operator
 WHERE oprname = '?|'
   AND oprleft = (SELECT oid FROM pg_type WHERE typname = 'jsonb');

Totéž pro rodinu operátorů (místo toho ji získáme z tabulky tříd operátorů), hledáme třídu gin, protože to je ta, která podporuje ?| . opcdefault se používá, protože existuje volitelná třída jsonb_path_ops který nepodporuje tento operátor:

SELECT opcfamily
  FROM pg_opclass
 WHERE opcintype = (SELECT oid FROM pg_type WHERE typname = 'jsonb')
   AND opcmethod = (SELECT oid FROM pg_am WHERE amname = 'gin')
   AND opcdefault

Poté získáme strategii použitou operátorem, který jsme duplikovali:

SELECT amopstrategy,
       (SELECT typname FROM pg_type WHERE oid = amoplefttype) AS left_t, 
       (SELECT typname FROM pg_type WHERE oid = amoprighttype) AS right_t,*
FROM pg_amop
WHERE amopfamily = 4036 --family oid
  AND amopopr = 3248 --operator oid

Potom funkce používané třídou:

SELECT amprocnum, amproc::text, pg_get_function_identity_arguments(amproc::oid) AS args,
      (SELECT typname FROM pg_type WHERE oid = amproclefttype) AS left_t,
      (SELECT typname FROM pg_type WHERE oid = amprocrighttype) AS right_t,*
FROM pg_amproc
WHERE amprocfamily = 4036 --op family

Tím se dostáváme k této třídě operátorů. Pokud již neexistuje, vytvoří rodinu operátorů.

CREATE OPERATOR CLASS jsonb_ops_custom
   FOR TYPE jsonb USING gin AS
   OPERATOR 10  ^|(jsonb, _text),
   FUNCTION 1  gin_compare_jsonb(text, text),
   FUNCTION 2  gin_extract_jsonb(jsonb, internal, internal),
   FUNCTION 3  gin_extract_jsonb_query(jsonb, internal, smallint, internal, internal, internal, internal),
   FUNCTION 4  gin_consistent_jsonb(internal, smallint, jsonb, integer, internal, internal, internal, internal),
   FUNCTION 6  gin_triconsistent_jsonb(internal, smallint, jsonb, integer, internal, internal, internal);

Nyní stačí vytvořit index pomocí názvu operátora, který byl vytvořen, něco jako:

CREATE INDEX ON jsonb_table USING gin(jsonb_column jsonb_ops_custom)

A měli byste být schopni používat index:

SET enable_seqscan = off;
EXPLAIN ANALYZE
SELECT * FROM jsonb_table WHERE jsonb_column ^| array['b', 'c'];


  1. Jaká je výhoda zerofill v MySQL?

  2. Může na jedné tabulce existovat více primárních klíčů?

  3. PDO načte jeden sloupec z tabulky do 1-rozměrného pole

  4. Časté chyby DBA v MS SQL Server