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 !! :(

Mayank
źródło
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.

Grzegorz Szpetkowski
źródło
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
);
Piotr Olaszewski
źródło
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.

Hendrik Brummermann
źródło
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    
Sombriks
źródło
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
2
insert into TABLENAMEA (A,B,C,D) 
select A::integer,B,C,D from TABLENAMEB
mahesh ingale
źródło
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>;
Nitin Nain
źródło