PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Convertir rapidement des tableaux Python vers PostgreSQL ?

Configuration

Vous souhaitez créer des déclencheurs (à plusieurs reprises ?) En utilisant la même fonction de déclencheur, comme indiqué dans ma réponse connexe sur dba.SE . Vous devez transmettre des valeurs à la fonction de déclenchement pour créer multiple lignes avec multiple valeurs de colonne, d'où le tableau à deux dimensions. (Mais nous pouvons travailler avec tout chaîne clairement définie !)

La seule façon de passer des valeurs à une fonction de déclenchement PL/pgSQL (autres que les valeurs de colonne de la ligne de déclenchement) est text paramètres, qui sont accessibles à l'intérieur de la fonction en tant que 0- basé sur un tableau de texte dans la variable de tableau spéciale TG_ARGV[] . Vous pouvez passer un nombre variable de paramètres, mais nous avons discuté plus tôt d'un seul littéral de chaîne représentant votre tableau à 2 dimensions.

L'entrée provient d'un tableau Python bidimensionnel avec entier signé nombres, qui correspondent au type Postgres integer . Utilisez le type Postgres bigint pour couvrir les nombres entiers non signés, comme commenté .

La représentation textuelle en Python ressemble à ceci :

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

Syntaxe pour un littéral de tableau Postgres :

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

Et vous souhaitez automatiser le processus.

Automatisation complète

Vous pouvez concaténer la chaîne pour le CREATE TRIGGER dans votre client ou vous pouvez conserver la logique dans une fonction côté serveur et simplement passer des paramètres.

Démonstration d'un exemple de fonction prenant un nom de table et la chaîne transmise à la fonction de déclenchement. La fonction de déclenchement insaft_function() est défini dans votre question précédente sur 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$;

Appel :

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

Ou :

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

db<>violon ici
Ancien sqlfiddle

Vous pouvez maintenant passer soit [[1,2],[3,4]] (entre crochets) ou {{1,2},{3,4}} (avec accolades). Les deux fonctionnent de la même manière. translate(_arg0, '[]', '{}' transforme la première en la seconde forme.

Cette fonction supprime un déclencheur du même nom s'il existe, avant d'en créer un nouveau. Vous pouvez supprimer ou conserver cette ligne :

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

Cela s'exécute avec les privilèges du rôle de base de données appelant. Vous pouvez le faire fonctionner avec des privilèges de superutilisateur (ou tout autre) si nécessaire. Voir :

Il existe de nombreuses façons d'y parvenir. Cela dépend des exigences exactes.

Expliquer format()

format() et le type de données regclass aider à concaténer en toute sécurité la commande DDL et à rendre l'injection SQL impossible. Voir :

Le premier argument est la "chaîne de format", suivi des arguments à intégrer dans la chaîne. J'utilise dollar-quoting , ce qui n'est pas strictement nécessaire pour l'exemple, mais généralement une bonne idée pour concaténer de longues chaînes contenant des guillemets simples :$$DROP TRIGGER ... $$

format() est modélisé le long de la fonction C sprintf . %1$s est un spécificateur de format du format() fonction. Cela signifie que le premier (1$ ) après l'insertion de la chaîne de format en tant que chaîne sans guillemets (%s ), d'où :%1$s . Le premier argument à formater est _tbl dans l'exemple - le regclass le paramètre est automatiquement rendu en tant qu'identifiant légal, entre guillemets si nécessaire, donc format() n'a pas à faire plus. Donc juste %s , pas %I (identifiant). Lisez la réponse liée ci-dessus pour plus de détails.
L'autre spécificateur de format utilisé est %2$L  :Deuxième argument en tant que littéral de chaîne entre guillemets .

Si vous débutez avec format() , jouez avec ces exemples simples pour comprendre :

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

Et lisez le manuel .