sql >> Database >  >> RDS >> PostgreSQL

Snel converteren van Python-arrays naar PostgreSQL?

Instellen

U wilt (herhaaldelijk?) triggers maken met dezelfde triggerfunctie zoals beschreven in mijn gerelateerde antwoord op dba.SE . U moet waarden doorgeven aan de triggerfunctie om meerdere te maken rijen met meerdere kolomwaarden, vandaar de tweedimensionale matrix. (Maar we kunnen werken met elke duidelijk gedefinieerde string!)

De enige manier om waarden door te geven aan een PL/pgSQL-triggerfunctie (anders dan kolomwaarden van de activerende rij) is text parameters, die binnen de functie toegankelijk zijn als 0- gebaseerde array van tekst in de speciale arrayvariabele TG_ARGV[] . U kunt een variabel aantal parameters doorgeven, maar we hebben eerder een enkele letterlijke tekenreeks besproken die uw 2-dimensionale array vertegenwoordigt.

Invoer komt van een 2-dimensionale Python-array met ondertekend geheel getal getallen, die passen in het Postgres-type integer . Gebruik het Postgres-type bigint om ongetekende gehele getallen te dekken, als heeft gereageerd .

De tekstrepresentatie in Python ziet er als volgt uit:

[[1,2],[3,4]]

Syntaxis voor een letterlijke Postgres-array:

{{1,2},{3,4}}

En u wilt het proces automatiseren.

Volledige automatisering

U kunt de tekenreeks samenvoegen voor de CREATE TRIGGER statement in uw client of u kunt de logica in een server-side functie behouden en gewoon parameters doorgeven.

Demonstratie van een voorbeeldfunctie met een tabelnaam en de tekenreeks die wordt doorgegeven aan de triggerfunctie. De triggerfunctie insaft_function() is gedefinieerd in uw vorige vraag op dba.SE .

CREATE OR REPLACE FUNCTION f_create_my_trigger(_tbl regclass, _arg0 text)
  RETURNS void
  LANGUAGE plpgsql AS
$func$
BEGIN
   EXECUTE format($$
      DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
      CREATE TRIGGER insaft_%1$s_ids
      AFTER INSERT ON %1$s
      FOR EACH ROW EXECUTE PROCEDURE insaft_function(%2$L)$$
                , _tbl
                , translate(_arg0, '[]', '{}')
      );
END 
$func$;

Bel:

SELECT f_create_my_trigger('measurements', '[[1,2],[3,4]]');

Of:

SELECT f_create_my_trigger('some_other_table', '{{5,6},{7,8}}');

db<>fiddle hier
Oude sqlfiddle

Nu kun je ofwel [[1,2],[3,4]] (met vierkante haken) of {{1,2},{3,4}} (met accolades). Beide werken hetzelfde. translate(_arg0, '[]', '{}' transformeert de eerste in de tweede vorm.

Deze functie laat een trigger met dezelfde naam vallen als deze bestaat, voordat de nieuwe wordt gemaakt. Misschien wilt u deze regel laten vallen of behouden:

DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;

Dit wordt uitgevoerd met de privileges van de aanroepende DB-rol. Je zou het indien nodig kunnen laten draaien met superuser (of andere) privileges. Zie:

Er zijn veel manieren om dit te bereiken. Het hangt af van de exacte vereisten.

Uitleg format()

format() en het gegevenstype regclass helpen om het DDL-commando veilig samen te voegen en SQL-injectie onmogelijk te maken. Zie:

Het eerste argument is de "format string", gevolgd door argumenten die in de string moeten worden ingesloten. Ik gebruik dollar-quoting , wat niet strikt noodzakelijk is voor het voorbeeld, maar over het algemeen een goed idee voor het aaneenschakelen van lange tekenreeksen met enkele aanhalingstekens:$$DROP TRIGGER ... $$

format() is gemodelleerd langs de C-functie sprintf . %1$s is een formaatspecificatie van het format() functie. Het betekent dat de eerste (1$ ) argument nadat de opmaaktekenreeks is ingevoegd als niet-aangehaalde tekenreeks (%s ), vandaar:%1$s . Het eerste argument om te formatteren is _tbl in het voorbeeld - de regclass parameter wordt automatisch weergegeven als legale identifier, indien nodig dubbele aanhalingstekens, dus format() hoeft niet meer te doen. Vandaar gewoon %s , niet %I (identificatienummer). Lees het gekoppelde antwoord hierboven voor details.
De andere gebruikte formaatspecificatie is %2$L :Tweede argument als letterlijke tekenreeks tussen aanhalingstekens .

Als u nieuw bent bij format() , speel met deze eenvoudige voorbeelden om het te begrijpen:

SELECT format('input -->|%s|<-- here', '[1,2]')
     , format('input -->|%s|<-- here', translate('[1,2]', '[]', '{}'))
     , format('input -->|%L|<-- here', translate('[1,2]', '[]', '{}'))
     , format('input -->|%I|<-- here', translate('[1,2]', '[]', '{}'));

En lees de handleiding .




  1. Fout 1329:Geen gegevens - nul rijen opgehaald, geselecteerd of verwerkt - zelfs als alles goed is gedaan

  2. Mariadb - Elke batch met verlengde uitvoeringstijd voor inserts neemt geleidelijk toe

  3. hoe de database in mysql te herstellen?

  4. Bulk postgres invoegen waar tijdstempel een null-beperking heeft ingesteld via sequalize