sql >> Database teknologi >  >> RDS >> PostgreSQL

Sådan undslipper du spørgsmålstegn (?) med Spring JpaRepository

I tilfælde af at undslippe ? er ikke muligt, kan du oprette duplikatoperatør med et andet navn.

Ny operatør

Syntaks til oprettelse af operatorer i 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 ]
)

I tilfælde af ?| brugt i jsonb det bliver:

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

Jeg har brugt ^| som et eksempel, alternativt navn. Det kan være en hvilken som helst sekvens fra denne liste:+ - * / < > = ~ ! @ # % ^ & | ?`.

Du kan finde den aktuelle definition for operatør, du er interesseret i, ved at forespørge pg_catalog.pg_operator table.

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

Du kan også bruge GUI-værktøj som pgAdmin og gennemse pg_catalog for at få SQL-definition klar til genbrug.

Aktiver indeks

Hvis du vil bruge indeks til denne "nye" operator, skal du oprette en ny operatorklasse og eventuelt familie. I vores tilfælde har vi brug for begge dele, da vi ikke kan tilføje det til eksisterende familie, fordi standardoperatøren allerede tager strategiplads.

Ligesom med operatører, anbefales det at bruge GUI-værktøj som pgAdmin til at gennemse operatørklasser og bare kopiere og indsætte det.

Først tager vi OID for den operatør, vi lavede duplikat af:

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

Det samme for operatørfamilien (vi får det fra operatørklassetabellen i stedet), vi leder efter gin-klasse, da dette er den, der understøtter ?| . opcdefault bruges, fordi der er valgfri klasse jsonb_path_ops der ikke understøtter denne operatør:

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

Så får vi strategi brugt af operatør, vi duplikerede:

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

Derefter funktioner brugt af klassen:

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

Dette bringer os til denne operatørklasse. Den vil oprette operatørfamilie, hvis den ikke allerede eksisterer.

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);

Nu skal du bare oprette et indeks ved at bruge det oprettede operatørnavn, sådan som:

CREATE INDEX ON jsonb_table USING gin(jsonb_column jsonb_ops_custom)

Og du burde kunne bruge index:

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


  1. PostgreSQL sletning med indre joinforbindelse

  2. Hvordan @@MAX_CONNECTIONS virker i SQL Server

  3. Konverter månedsnummer til månedsnavn i PostgreSQL

  4. Laravel 5.2 - Brug en streng som en tilpasset primær nøgle til veltalende tabel bliver 0