PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Um schnell von Python-Arrays zu PostgreSQL zu konvertieren?

Einrichtung

Sie möchten Trigger (wiederholt?) mit derselben Triggerfunktion erstellen, wie in my Related answer on beschrieben dba.SE . Sie müssen Werte an die Triggerfunktion übergeben, um mehrere zu erstellen Zeilen mit mehreren Spaltenwerte, daher das zweidimensionale Array. (Aber wir können mit jedem arbeiten klar definierter String!)

Die einzige Möglichkeit, Werte an eine PL/pgSQL-Triggerfunktion zu übergeben (anders als Spaltenwerte der auslösenden Zeile), ist text Parameter, auf die innerhalb der Funktion zugegriffen werden kann als 0- basierendes Array von Text in der speziellen Array-Variablen TG_ARGV[] . Sie können eine variable Anzahl von Parametern übergeben, aber wir haben bereits ein einzelnes String-Literal besprochen, das Ihr zweidimensionales Array darstellt.

Die Eingabe kommt von einem zweidimensionalen Python-Array mit vorzeichenbehafteter Ganzzahl Zahlen, die in den Postgres-Typ integer passen . Verwenden Sie den Postgres-Typ bigint um vorzeichenlose Ganzzahlen abzudecken, as kommentiert .

Die Textdarstellung in Python sieht so aus:

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

Syntax für ein Postgres-Array-Literal:

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

Und Sie möchten den Prozess automatisieren.

Vollständige Automatisierung

Sie können die Zeichenfolge für den CREATE TRIGGER verketten -Anweisung in Ihrem Client oder Sie können die Logik in einer serverseitigen Funktion beibehalten und einfach Parameter übergeben.

Demonstrieren einer Beispielfunktion mit einem Tabellennamen und der Zeichenfolge, die an die Triggerfunktion übergeben wird. Die Triggerfunktion insaft_function() ist in Ihrer vorherigen Frage zu dba.SE definiert .

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

Aufruf:

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

Oder:

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

db<>fiddle hier
Altes sqlfiddle

Jetzt können Sie entweder [[1,2],[3,4]] übergeben (mit eckigen Klammern) oder {{1,2},{3,4}} (mit geschweiften Klammern). Beide funktionieren gleich. translate(_arg0, '[]', '{}' wandelt die erste in die zweite Form um.

Diese Funktion löscht einen Trigger mit demselben Namen, falls vorhanden, bevor der neue erstellt wird. Sie können diese Zeile löschen oder beibehalten:

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

Dieser läuft mit den Privilegien der aufrufenden DB-Rolle. Sie können es bei Bedarf mit Superuser- (oder anderen) Rechten ausführen lassen. Siehe:

Es gibt viele Möglichkeiten, dies zu erreichen. Es hängt von den genauen Anforderungen ab.

Erläuterung von format()

format() und dem Datentyp regclass helfen, den DDL-Befehl sicher zu verketten und die SQL-Einschleusung unmöglich zu machen. Siehe:

Das erste Argument ist der "Formatstring", gefolgt von Argumenten, die in den String eingebettet werden sollen. Ich verwende Dollar-Quoting , was für das Beispiel nicht unbedingt erforderlich ist, aber im Allgemeinen eine gute Idee zum Verketten langer Zeichenfolgen mit einfachen Anführungszeichen ist:$$DROP TRIGGER ... $$

format() ist der C-Funktion sprintf nachempfunden . %1$s ist ein Formatbezeichner des format() Funktion. Das bedeutet, dass die erste (1$ ) Argument, nachdem der Formatstring als String ohne Anführungszeichen eingefügt wird (%s ), also:%1$s . Das erste zu formatierende Argument ist _tbl im Beispiel - die regclass Der Parameter wird automatisch als legaler Bezeichner gerendert, falls erforderlich, in doppelte Anführungszeichen, also format() mehr muss man nicht machen. Also nur %s , nicht %I (Kennung). Lesen Sie die verlinkte Antwort oben für Details.
Der andere verwendete Formatbezeichner ist %2$L :Zweites Argument als String-Literal in Anführungszeichen .

Wenn Sie neu bei format() sind , spielen Sie mit diesen einfachen Beispielen, um zu verstehen:

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]', '[]', '{}'));

Und lesen Sie das Handbuch .