postgresql: INSERT INTO… (SELECT *…)


125

Non sono sicuro che sia SQL standard:

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

Quello che sto cercando è: cosa succede se tblA e tblB si trovano in server DB diversi .

PostgreSql fornisce qualsiasi utilità o ha funzionalità che aiuteranno a utilizzare INSERT query with PGresult struct

Voglio dire SELECT id, time FROM tblB ...che restituirà un PGresult*utilizzo PQexec. È possibile utilizzare questa struttura in un'altra PQexecper eseguire un comando INSERT.

EDIT:
Se non è possibile, vorrei estrarre i valori da PQresult * e creare una sintassi di istruzioni INSERT multipla come:

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

È possibile creare una dichiarazione preparata da questo !! :(


Non so se la sintassi INSERT che hai pubblicato sia ANSI, ma è ampiamente supportata (Oracle, MySQL, SQL Server, SQLite ...). Ma le parentesi non sono necessarie.
OMG Ponies

Risposte:


152

Come ha scritto Henrik, puoi usare dblink per connettere il database remoto e recuperare il risultato. Per esempio:

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 ha uno pseudo-tipo di record (solo per l'argomento della funzione o il tipo di risultato), che consente di interrogare i dati da un'altra tabella (sconosciuta).

Modificare:

Puoi renderlo come una dichiarazione preparata se vuoi e funziona anche:

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;

Modifica (sì, un altro):

Ho appena visto la tua domanda rivista (chiusa come duplicata o semplicemente molto simile a questa).

Se la mia comprensione è corretta (postgres ha tbla e dbtest ha tblb e si desidera l'inserimento remoto con selezione locale , non la selezione remota con inserimento locale come sopra):

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;'
);

Non mi piace quel dblink annidato, ma AFAIK non posso fare riferimento a tblB nel corpo di dblink_exec . Usa LIMIT per specificare le prime 20 righe, ma penso che devi prima ordinarle usando la clausola ORDER BY.


1
Grazie per la risposta. Bene, un'altra domanda veloce ... INSERT INTO tblA SELECT id, time FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB') AS t(id integer, time integer) WHERE time > 1000; Posso fare una dichiarazione preparata da questo?
Mayank

Ciao @ grzegorz-szpetkowski, Questa logica sta dando un errore: ERRORE: la password è richiesta DETTAGLIO: I non superutenti devono fornire una password nella stringa di connessione.
Neel Darji

34

Se vuoi inserire nella colonna specifica:

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

9

È possibile utilizzare dblink per creare una vista che viene risolta in un altro database. Questo database potrebbe trovarsi su un altro server.


Grazie per la risposta. Ma non ho capito come INSERT INTO ... (SELECT FROM ...)funzionerà usando dblink. Quello di cui ho bisogno è INSERT INTO ...di essere eseguito in una sessione dblink su un altro DB Server, ma (SELECT FROM ...)nella mia sessione corrente.
Mayank

Devi solo definire tblA come vista supportata da dblink. Quindi inserimenti, aggiornamenti, eliminazioni verranno effettuati nell'altro database. dblink non è di sola lettura.
Hendrik Brummermann

9

Anche questa notazione (vista per la prima volta qui ) sembra utile:

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

2
Funziona solo quando le tabelle si trovano nello stesso database. La domanda riguarda la copia dei dati da una tabella in un database diverso .
Nitin Nain

2
insert into TABLENAMEA (A,B,C,D) 
select A::integer,B,C,D from TABLENAMEB

1

Ecco una soluzione alternativa, senza utilizzare dblink .

Supponiamo che B rappresenti il ​​database di origine e A rappresenti il ​​database di destinazione: quindi,

  1. Copia la tabella dal DB di origine al DB di destinazione:

    pg_dump -t <source_table> <source_db> | psql <target_db>
  2. Apri il prompt di psql, connettiti a target_db e usa un semplice insert:

    psql
    # \c <target_db>;
    # INSERT INTO <target_table>(id, x, y) SELECT id, x, y FROM <source_table>;
  3. Alla fine, elimina la copia di source_table che hai creato in target_table .

    # DROP TABLE <source_table>;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.