postgresql: INSERT INTO… (SELECT *…)


125

Bunun standart SQL olup olmadığından emin değilim:

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

Aradığım şey: tblA ve tblB farklı DB Sunucularında ise ne olur ?

PostgreSql herhangi bir yardımcı program veriyor mu veya kullanıma yardımcı olacak herhangi bir işlevi var mı? INSERT query with PGresult struct

Demek istediğim kullanarak SELECT id, time FROM tblB ...geri dönecekPGresult*PQexec . Bu yapıyı başka PQexecbir INSERT komutunu çalıştırmak için kullanmak mümkün mü ?

DÜZENLEME:
Mümkün değilse, değerleri PQresult * 'dan çıkarır ve aşağıdaki gibi birden çok INSERT ifadesi sözdizimi oluştururum:

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

Bundan hazırlanmış bir ifade oluşturmak mümkün mü !! :(


Gönderdiğiniz INSERT sözdiziminin ANSI olup olmadığını bilmiyorum, ancak yaygın olarak destekleniyor (Oracle, MySQL, SQL Server, SQLite ...). Ancak parantezler gerekli değildir.
OMG Ponies

Yanıtlar:


152

Henrik'in yazdığı gibi, uzak veritabanına bağlanmak ve sonucu almak için dblink'i kullanabilirsiniz. Örneğin:

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'in kaydı var başka bir (bilinmeyen) tablodan veri sorgulamanıza izin veren sözde türüne sahiptir (yalnızca işlevin argümanı veya sonuç türü için).

Düzenle:

İsterseniz hazır bir açıklama olarak yapabilirsiniz ve o da işe yarar:

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;

Düzenle (evet, başka):

Az önce gözden geçirilmiş sorunuzu gördüm (mükerrer olarak kapatılmış veya buna çok benzer).

Anladığım doğruysa (postgres tbla'ya sahipse ve dbtest tblb'ye sahipse ve yukarıdaki gibi yerel ekleme ile uzaktan seçim değil, yerel seçim ile uzak giriş istiyorsanız ):

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

İç içe geçmiş dblink'i sevmiyorum, ancak AFAIK dblink_exec gövdesinde tblB'ye başvuramıyorum . İlk 20 satırı belirtmek için LIMIT kullanın, ancak bunları önce ORDER BY yan tümcesini kullanarak sıralamanız gerektiğini düşünüyorum.


1
Cevabınız için teşekkürler. Pekala, hızlı bir soru daha ... Bundan INSERT INTO tblA SELECT id, time FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB') AS t(id integer, time integer) WHERE time > 1000; önceden hazırlanmış bir açıklama yapabilir miyim?
Mayank

Merhaba @ grzegorz-szpetkowski, Bu mantık hata veriyor: HATA: şifre gerekli DETAY: Üstün kullanıcı olmayanlar bağlantı dizesinde bir şifre girmelidir.
Neel Darji

34

Belirtme sütununa eklemek isterseniz:

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

9

Başka bir veritabanında çözülen bir görünüm oluşturmak için dblink'i kullanabilirsiniz . Bu veritabanı başka bir sunucuda olabilir.


Cevap için teşekkürler. Ama INSERT INTO ... (SELECT FROM ...)dblink kullanarak nasıl çalışacağımı anlamadım . İhtiyacım olan şey INSERT INTO ..., dblink oturumunda başka bir DB Sunucusuna, ancak (SELECT FROM ...)mevcut oturumumda çalıştırılmak.
Mayank

TblA'yı dblink tarafından desteklenen görünüm olarak tanımlarsınız. Böylece diğer veri tabanında eklemeler, güncellemeler, silmeler yapılacaktır. dblink salt okunur değildir.
Hendrik Brummermann

9

Bu gösterim (ilk olarak burada görülmüştür ) da yararlı görünüyor:

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

2
Bu yalnızca tablolar aynı veritabanında olduğunda çalışır. Soru, verilerin bir farklı bir veritabanındaki tablodan .
Nitin Nain


1

İşte kullanmadan alternatif bir çözüm dblink .

B'nin kaynak veritabanını ve A'nın hedef veritabanını temsil ettiğini varsayalım:

  1. Tabloyu kaynak DB'den hedef DB'ye kopyalayın:

    pg_dump -t <source_table> <source_db> | psql <target_db>
  2. Psql komut istemini açın, target_db'ye bağlanın ve basit bir yöntem kullanın insert:

    psql
    # \c <target_db>;
    # INSERT INTO <target_table>(id, x, y) SELECT id, x, y FROM <source_table>;
  3. Sonunda, kopyasını silmek source_table oluşturduğunuz o target_table .

    # DROP TABLE <source_table>;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.