postgresql: INSERT INTO… (SELECT *…)


125

Nie jestem pewien, czy jego standardowy SQL:

 INSERT INTO tblA 
 (SELECT id, time 
    FROM tblB 
   WHERE time > 1000)  

To, czego szukam, to: co, jeśli tblA i tblB znajdują się na różnych serwerach DB .

Czy PostgreSql udostępnia jakieś narzędzie lub ma jakąkolwiek funkcjonalność, która pomoże w użyciu INSERT query with PGresult struct

Mam na myśli, SELECT id, time FROM tblB ...że zwróci PGresult*przy użyciu PQexec. Czy można użyć tej struktury w innej, PQexecaby wykonać polecenie INSERT.

EDYCJA:
Jeśli nie jest to możliwe, chciałbym wyodrębnić wartości z PQresult * i utworzyć składnię wielu instrukcji INSERT, takich jak:

INSERT INTO films (code, title, did, date_prod, kind) VALUES
    ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
    ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy'); 

Czy da się z tego stworzyć przygotowane zestawienie !! :(


Nie wiem, czy podana przez ciebie składnia INSERT to ANSI, ale jest szeroko obsługiwana (Oracle, MySQL, SQL Server, SQLite ...). Ale nawiasy nie są konieczne.
Kucyki OMG

Odpowiedzi:


153

Jak napisał Henrik, możesz użyć dblink do połączenia ze zdalną bazą danych i pobrania wyniku. Na przykład:

psql dbtest
CREATE TABLE tblB (id serial, time integer);
INSERT INTO tblB (time) VALUES (5000), (2000);

psql postgres
CREATE TABLE tblA (id serial, time integer);

INSERT INTO tblA
    SELECT id, time 
    FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB')
    AS t(id integer, time integer)
    WHERE time > 1000;

TABLE tblA;
 id | time 
----+------
  1 | 5000
  2 | 2000
(2 rows)

PostgreSQL ma pseudotyp rekordu (tylko dla argumentu funkcji lub typu wyniku), który pozwala na odpytywanie danych z innej (nieznanej) tabeli.

Edytować:

Możesz zrobić to jako przygotowane oświadczenie, jeśli chcesz i również działa:

PREPARE migrate_data (integer) AS
INSERT INTO tblA
    SELECT id, time
    FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB')
    AS t(id integer, time integer)
    WHERE time > $1;

EXECUTE migrate_data(1000);
-- DEALLOCATE migrate_data;

Edytuj (tak, inny):

Właśnie zobaczyłem Twoje poprawione pytanie (zamknięte jako zduplikowane lub bardzo podobne do tego).

Jeśli moje rozumienie jest poprawne (postgres ma tbla i dbtest ma tblb i chcesz zdalnego wkładkę z lokalnym select , nie zdalnego wybierz z lokalnym wkładką jak wyżej):

psql dbtest

SELECT dblink_exec
(
    'dbname=postgres',
    'INSERT INTO tbla
        SELECT id, time
        FROM dblink
        (
            ''dbname=dbtest'',
            ''SELECT id, time FROM tblb''
        )
        AS t(id integer, time integer)
        WHERE time > 1000;'
);

Nie podoba mi się ten zagnieżdżony dblink, ale AFAIK nie mogę odwoływać się do tblB w treści dblink_exec . Użyj LIMIT, aby określić 20 pierwszych wierszy, ale myślę, że najpierw musisz je posortować za pomocą klauzuli ORDER BY.


1
Dzięki za twoją odpowiedź. Cóż, jeszcze jedno szybkie pytanie ... INSERT INTO tblA SELECT id, time FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB') AS t(id integer, time integer) WHERE time > 1000; Czy mogę zrobić z tego przygotowane oświadczenie?
Mayank

Cześć @ grzegorz-szpetkowski, Ta logika podaje błąd: BŁĄD: wymagane jest hasło SZCZEGÓŁY: Użytkownicy niebędący superużytkownikami muszą podać hasło w ciągu połączenia.
Neel Darji

34

Jeśli chcesz wstawić do określonej kolumny:

INSERT INTO table (time)
(SELECT time FROM 
    dblink('dbname=dbtest', 'SELECT time FROM tblB') AS t(time integer) 
    WHERE time > 1000
);

9

Możesz użyć dblink, aby utworzyć widok, który zostanie rozwiązany w innej bazie danych. Ta baza danych może znajdować się na innym serwerze.


Dziękuję za odpowiedź. Ale nie rozumiem, jak INSERT INTO ... (SELECT FROM ...)będzie działać za pomocą dblink. To, czego potrzebuję, to INSERT INTO ...uruchomienie w sesji dblink na innym serwerze DB, ale (SELECT FROM ...)w mojej bieżącej sesji.
Mayank

Po prostu definiujesz tblA jako widok wspierany przez dblink. Więc wstawienia, aktualizacje, usunięcia będą wykonywane w innej bazie danych. dblink nie jest tylko do odczytu.
Hendrik Brummermann

9

Ta notacja (po raz pierwszy pokazana tutaj ) również wygląda przydatna:

insert into postagem (
  resumopostagem,
  textopostagem,
  dtliberacaopostagem,
  idmediaimgpostagem,
  idcatolico,
  idminisermao,
  idtipopostagem
) select
  resumominisermao,
  textominisermao,
  diaminisermao,
  idmediaimgminisermao,
  idcatolico ,
  idminisermao,
  1
from
  minisermao    

2
Działa to tylko wtedy, gdy tabele znajdują się w tej samej bazie danych. Pytanie dotyczy kopiowania danych z tabeli w innej bazie danych .
Nitin Nain


1

Oto alternatywne rozwiązanie bez użycia dblink.

Załóżmy, że B reprezentuje źródłową bazę danych, a A reprezentuje docelową bazę danych: Następnie

  1. Skopiuj tabelę ze źródłowej bazy danych do docelowej bazy danych:

    pg_dump -t <source_table> <source_db> | psql <target_db>
  2. Otwórz znak zachęty psql, połącz się z target_db i użyj prostego insert:

    psql
    # \c <target_db>;
    # INSERT INTO <target_table>(id, x, y) SELECT id, x, y FROM <source_table>;
  3. Na koniec usuń kopię tabeli source_table , którą utworzyłeś w target_table .

    # DROP TABLE <source_table>;
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.