PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Aby szybko przekonwertować tablice Pythona na PostgreSQL?

Konfiguracja

Chcesz utworzyć wyzwalacze (wielokrotnie?) Za pomocą tej samej funkcji wyzwalacza, jak opisano w moja powiązana odpowiedź na dba.SE . Musisz przekazać wartości do funkcji wyzwalacza, aby utworzyć wiele wiersze z wieloma wartości kolumn, stąd dwuwymiarowa tablica. (Ale możemy pracować z każdym wyraźnie zdefiniowany ciąg!)

Jedynym sposobem przekazania wartości do funkcji wyzwalającej PL/pgSQL (innej niż wartości kolumn w wierszu wyzwalającym) jest text parametry, które są dostępne wewnątrz funkcji jako 0- oparta tablica tekstu w specjalnej zmiennej tablicowej TG_ARGV[] . Możesz przekazać zmienną liczbę parametrów, ale omówiliśmy wcześniej pojedynczy literał ciągu reprezentujący twoją dwuwymiarową tablicę.

Dane wejściowe pochodzą z dwuwymiarowej tablicy Pythona z liczbą całkowitą ze znakiem liczby, które pasują do Postgresa typu integer . Użyj Postgresa typu bigint aby pokryć liczby całkowite bez znaku, jako skomentował .

Reprezentacja tekstowa w Pythonie wygląda tak:

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

Składnia literału tablicy Postgres:

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

I chcesz zautomatyzować ten proces.

Pełna automatyzacja

Możesz połączyć ciąg dla CREATE TRIGGER w swoim kliencie lub możesz utrwalić logikę w funkcji po stronie serwera i po prostu przekazać parametry.

Demonstracja przykładowej funkcji pobierającej nazwę tabeli i ciąg, który jest przekazywany do funkcji wyzwalacza. Funkcja wyzwalacza insaft_function() jest zdefiniowany w poprzednim pytaniu na 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$;

Zadzwoń:

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

Lub:

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

db<>fiddle tutaj
Stary sqlfiddle

Teraz możesz przekazać albo [[1,2],[3,4]] (z nawiasami kwadratowymi) lub {{1,2},{3,4}} (z nawiasami klamrowymi). Obie działają tak samo. translate(_arg0, '[]', '{}' przekształca pierwszą w drugą formę.

Ta funkcja usuwa wyzwalacz o tej samej nazwie, jeśli istnieje, przed utworzeniem nowego. Możesz zrezygnować lub zachować tę linię:

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

Działa to z uprawnieniami wywołującej roli DB. W razie potrzeby możesz uruchomić go z uprawnieniami superużytkownika (lub dowolnymi innymi). Zobacz:

Istnieje wiele sposobów, aby to osiągnąć. To zależy od dokładnych wymagań.

Objaśnienie format()

format() i typ danych regclass pomagają bezpiecznie łączyć polecenie DDL i uniemożliwiają wstrzykiwanie SQL. Zobacz:

Pierwszym argumentem jest „ciąg formatu”, po którym następują argumenty, które mają zostać osadzone w ciągu. Używam cytowania dolarów , co nie jest konieczne w tym przykładzie, ale ogólnie jest dobrym pomysłem na łączenie długich ciągów zawierających pojedyncze cudzysłowy:$$DROP TRIGGER ... $$

format() jest wzorowany na funkcji C sprintf . %1$s jest specyfikatorem formatu format( ) funkcjonować. Oznacza to, że pierwszy (1$ ) argument po wstawieniu ciągu formatu jako ciąg bez cudzysłowu (%s ), stąd:%1$s . Pierwszym argumentem do formatowania jest _tbl w przykładzie - regclass parametr jest automatycznie renderowany jako prawidłowy identyfikator, w razie potrzeby w cudzysłowie, więc format() nie musi robić więcej. Stąd po prostu %s , a nie %I (identyfikator). Przeczytaj odpowiedź z linkiem powyżej, aby uzyskać szczegółowe informacje.
Inny używany specyfikator formatu to %2$L :Drugi argument jako cytowany literał ciągu .

Jeśli jesteś nowy w format() , pobaw się tymi prostymi przykładami, aby zrozumieć:

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

I przeczytaj instrukcję .




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oblicz Max of Sum pola z adnotacjami w pogrupowanym zapytaniu w Django ORM?

  2. strapi database.js / konfiguracje wielu baz danych

  3. Jak UNION listę tabel pobranych z innej tabeli za pomocą jednego zapytania?

  4. Problem z uprawnieniami do PostgreSQL w kontenerze docker

  5. Jaka jest różnica między pg_table_size, pg_relation_size i pg_total_relation_size? (PostgreSQL)