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.