postgresql: MASUKKAN KE… (PILIH *…)

125

Saya tidak yakin apakah SQL standarnya:

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

Apa yang saya cari adalah: bagaimana jika tblA dan tblB berada di Server DB yang berbeda .

Apakah PostgreSql memberikan utilitas apa pun atau memiliki fungsi apa pun yang akan membantu untuk digunakan INSERT query with PGresult struct

Maksud saya SELECT id, time FROM tblB ...akan kembali PGresult*menggunakan PQexec. Apakah mungkin untuk menggunakan struct ini di lain PQexecuntuk menjalankan perintah INSERT.

EDIT:
Jika tidak memungkinkan maka saya akan mengekstraksi nilai dari PQresult * dan membuat beberapa sintaks pernyataan INSERT seperti:

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

Apakah mungkin untuk membuat pernyataan yang disiapkan dari ini !! :(

Mayank
sumber
Saya tidak tahu apakah sintaks INSERT yang Anda posting adalah ANSI, tetapi didukung secara luas (Oracle, MySQL, SQL Server, SQLite ...). Tetapi tanda kurung tidak diperlukan.
OMG Ponies

Jawaban:

152

Seperti yang ditulis Henrik, Anda dapat menggunakan dblink untuk menghubungkan database jarak jauh dan mengambil hasil. Sebagai contoh:

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 memiliki record pseudo-type (hanya untuk argumen fungsi atau jenis hasil), yang memungkinkan Anda melakukan kueri data dari tabel lain (tidak diketahui).

Edit:

Anda dapat menjadikannya sebagai pernyataan yang disiapkan jika Anda mau dan itu berfungsi juga:

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;

Edit (ya, lainnya):

Saya baru saja melihat pertanyaan Anda yang direvisi (ditutup sebagai duplikat, atau sangat mirip dengan ini).

Jika pemahaman saya benar (postgres memiliki tbla dan dbtest memiliki tblb dan Anda ingin memasukkan jarak jauh dengan pilih lokal , bukan pilih jarak jauh dengan sisipan lokal seperti di atas):

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

Saya tidak suka dblink bersarang itu, tetapi AFAIK saya tidak bisa merujuk ke tblB di dblink_exec body. Gunakan LIMIT untuk menentukan 20 baris teratas, tetapi saya pikir Anda perlu mengurutkannya menggunakan klausa ORDER BY terlebih dahulu.

Grzegorz Szpetkowski
sumber
1
Terimakasih atas tanggapan Anda. Nah, satu pertanyaan singkat lagi ... INSERT INTO tblA SELECT id, time FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB') AS t(id integer, time integer) WHERE time > 1000; Bolehkah saya membuat pernyataan yang dipersiapkan dari ini?
Mayank
Hai @ grzegorz-szpetkowski, Logika ini memberikan kesalahan: ERROR: password diperlukan DETAIL: Non-superusers harus memberikan password dalam string koneksi.
Neel Darji
34

Jika Anda ingin memasukkan ke kolom tentukan:

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

Anda dapat menggunakan dblink untuk membuat tampilan yang diselesaikan di database lain. Database ini mungkin ada di server lain.

Hendrik Brummermann
sumber
Terima kasih balasannya. Tapi saya tidak mengerti bagaimana cara INSERT INTO ... (SELECT FROM ...)kerja menggunakan dblink. Yang saya butuhkan adalah INSERT INTO ...menjalankan sesi dblink ke Server DB lain, tetapi (SELECT FROM ...)dalam sesi saya saat ini.
Mayank
Anda tinggal mendefinisikan tblA sebagai view yang didukung oleh dblink. Jadi penyisipan, pembaruan, penghapusan akan dilakukan di database lain. dblink tidak hanya bisa dibaca.
Hendrik Brummermann
9

Notasi ini (pertama kali terlihat di sini ) terlihat berguna juga:

insert into postagem (
  resumopostagem,
  textopostagem,
  dtliberacaopostagem,
  idmediaimgpostagem,
  idcatolico,
  idminisermao,
  idtipopostagem
) select
  resumominisermao,
  textominisermao,
  diaminisermao,
  idmediaimgminisermao,
  idcatolico ,
  idminisermao,
  1
from
  minisermao    
Sombriks
sumber
2
Ini hanya berfungsi jika tabel berada dalam database yang sama. Pertanyaannya adalah tentang menyalin data dari tabel di database yang berbeda .
Nitin Nain
2
insert into TABLENAMEA (A,B,C,D) 
select A::integer,B,C,D from TABLENAMEB
mahesh ingale
sumber
1

Berikut solusi alternatif, tanpa menggunakan dblink.

Misalkan B mewakili database sumber dan A mewakili database target: Kemudian,

  1. Salin tabel dari DB sumber ke DB target:

    pg_dump -t <source_table> <source_db> | psql <target_db>
  2. Buka prompt psql, sambungkan ke target_db , dan gunakan perintah sederhana insert:

    psql
    # \c <target_db>;
    # INSERT INTO <target_table>(id, x, y) SELECT id, x, y FROM <source_table>;
    
  3. Terakhir, hapus salinan source_table yang Anda buat di target_table .

    # DROP TABLE <source_table>;
Nitin Nain
sumber