postgresql: INSERT INTO … (SELECT * …)


125

ฉันไม่แน่ใจว่า SQL มาตรฐาน:

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

สิ่งที่ผมกำลังมองหาคือสิ่งที่ถ้า tblA และ tblB อยู่ในเซิร์ฟเวอร์ฐานข้อมูลที่แตกต่างกัน

PostgreSql ให้ยูทิลิตี้หรือมีฟังก์ชันใด ๆ ที่จะช่วยในการใช้งาน INSERT query with PGresult struct

ผมหมายถึงSELECT id, time FROM tblB ...จะกลับเกี่ยวกับการใช้PGresult* PQexecเป็นไปได้ไหมที่จะใช้โครงสร้างนี้ในโครงสร้างอื่นPQexecเพื่อเรียกใช้คำสั่ง INSERT

แก้ไข:
ถ้าเป็นไปไม่ได้ฉันจะไปแยกค่าจาก PQresult * และสร้างไวยากรณ์คำสั่ง INSERT หลายรายการเช่น:

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

เป็นไปได้หรือไม่ที่จะสร้างแถลงการณ์ที่เตรียมไว้จากสิ่งนี้ !! :(


ฉันไม่รู้ว่าไวยากรณ์ INSERT ที่คุณโพสต์เป็น ANSI หรือไม่ แต่ได้รับการสนับสนุนอย่างกว้างขวาง (Oracle, MySQL, SQL Server, SQLite ... ) แต่ไม่จำเป็นต้องใช้วงเล็บ
OMG Ponies

คำตอบ:


152

ตามที่ Henrik เขียนไว้คุณสามารถใช้ dblink เพื่อเชื่อมต่อฐานข้อมูลระยะไกลและดึงผลลัพธ์ ตัวอย่างเช่น:

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 มีการบันทึกประเภทหลอก (สำหรับอาร์กิวเมนต์ของฟังก์ชันหรือประเภทผลลัพธ์เท่านั้น) ซึ่งช่วยให้คุณสืบค้นข้อมูลจากตารางอื่น (ไม่ทราบ)

แก้ไข:

คุณสามารถทำให้เป็นคำสั่งที่เตรียมไว้ได้หากต้องการและใช้งานได้ดี

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;

แก้ไข (ใช่อื่น ๆ ):

ฉันเพิ่งเห็นคำถามของคุณที่แก้ไขแล้ว (ปิดแล้วว่าซ้ำกันหรือคล้ายกันมาก)

หากความเข้าใจของฉันถูกต้อง (postgres มี tbla และ dbtest มี tblb และคุณต้องการการแทรกระยะไกลด้วยการเลือกในเครื่องไม่ใช่การเลือกระยะไกลด้วยการแทรกในเครื่องตามด้านบน):

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

ฉันไม่ชอบ dblink ที่ซ้อนกัน แต่ AFAIK ฉันไม่สามารถอ้างอิงถึง tblB ในร่างกายdblink_exec ใช้ LIMIT เพื่อระบุ 20 แถวบนสุด แต่ฉันคิดว่าคุณต้องเรียงลำดับโดยใช้คำสั่ง ORDER BY ก่อน


1
ขอบคุณสำหรับคำตอบของคุณ คำถามสั้น ๆ อีกข้อหนึ่ง ... INSERT INTO tblA SELECT id, time FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB') AS t(id integer, time integer) WHERE time > 1000; ฉันสามารถเตรียมคำสั่งจากสิ่งนี้ได้หรือไม่?
Mayank

สวัสดี @ grzegorz-szpetkowski ตรรกะนี้ให้ข้อผิดพลาด: ข้อผิดพลาด: ต้องใช้รหัสผ่านรายละเอียด: ผู้ที่ไม่ใช่ผู้ใช้ขั้นสูงต้องระบุรหัสผ่านในสตริงการเชื่อมต่อ
Neel Darji

34

หากคุณต้องการแทรกลงในคอลัมน์ระบุ:

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

9

คุณสามารถใช้dblinkเพื่อสร้างมุมมองที่แก้ไขในฐานข้อมูลอื่น ฐานข้อมูลนี้อาจอยู่บนเซิร์ฟเวอร์อื่น


ขอบคุณสำหรับการตอบกลับ. แต่ฉันไม่เข้าใจวิธีการINSERT INTO ... (SELECT FROM ...)ทำงานโดยใช้ dblink สิ่งที่ฉันต้องการคือINSERT INTO ...ต้องรันในเซสชัน dblink ไปยัง DB Server อื่น แต่(SELECT FROM ...)ในเซสชันปัจจุบันของฉัน
Mayank

คุณเพียงแค่กำหนด tblA เป็นมุมมองที่ได้รับการสนับสนุนโดย dblink ดังนั้นการแทรกการอัปเดตการลบจะทำได้ในฐานข้อมูลอื่น dblink ไม่ได้อ่านอย่างเดียว
Hendrik Brummermann

9

สัญกรณ์นี้ (เห็นครั้งแรกที่นี่ ) ก็มีประโยชน์เช่นกัน:

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

2
สิ่งนี้ใช้ได้เฉพาะเมื่อตารางอยู่ในฐานข้อมูลเดียวกัน คำถามเกี่ยวกับการคัดลอกข้อมูลจากตารางในฐานข้อมูลอื่น
Nitin Nain


1

นี่เป็นวิธีอื่นโดยไม่ต้องใช้ dblinkนี่เป็นวิธีการแก้ปัญหาอื่นโดยไม่ต้องใช้

สมมติว่า B แทนฐานข้อมูลต้นทางและ A แทนฐานข้อมูลเป้าหมายจากนั้น

  1. คัดลอกตารางจากฐานข้อมูลต้นทางไปยังฐานข้อมูลเป้าหมาย:

    pg_dump -t <source_table> <source_db> | psql <target_db>
  2. เปิดพรอมต์ psql เชื่อมต่อกับtarget_dbและใช้วิธีง่ายๆinsert:

    psql
    # \c <target_db>;
    # INSERT INTO <target_table>(id, x, y) SELECT id, x, y FROM <source_table>;
  3. ในตอนท้ายลบสำเนาของsource_tableที่คุณสร้างในtarget_table

    # DROP TABLE <source_table>;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.