postgresql: CHÈN VÀO… (CHỌN *…)


125

Tôi không chắc liệu SQL chuẩn của nó:

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

Điều tôi đang tìm là: điều gì sẽ xảy ra nếu tblA và tblB nằm trong các Máy chủ DB khác nhau .

PostgreSql có cung cấp bất kỳ tiện ích nào hoặc có bất kỳ chức năng nào giúp sử dụng không INSERT query with PGresult struct

Tôi có nghĩa là SELECT id, time FROM tblB ...sẽ trả lại một PGresult*khi sử dụng PQexec. Có thể sử dụng cấu trúc này trong cấu trúc khác PQexecđể thực hiện một lệnh INSERT.

CHỈNH SỬA:
Nếu không thể thì tôi sẽ trích xuất các giá trị từ PQresult * và tạo cú pháp câu lệnh INSERT nhiều như:

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

Có thể tạo một tuyên bố chuẩn bị từ điều này không !! :(


Tôi không biết cú pháp INSERT bạn đăng có phải là ANSI hay không, nhưng nó được hỗ trợ rộng rãi (Oracle, MySQL, SQL Server, SQLite ...). Nhưng dấu ngoặc không cần thiết.
OMG Ponies

Câu trả lời:


152

Như Henrik đã viết, bạn có thể sử dụng dblink để kết nối cơ sở dữ liệu từ xa và tìm nạp kết quả. Ví dụ:

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 có kiểu giả bản ghi (chỉ dành cho đối số của hàm hoặc kiểu kết quả), cho phép bạn truy vấn dữ liệu từ một bảng (không xác định) khác.

Biên tập:

Bạn có thể làm cho nó như một tuyên bố chuẩn bị sẵn nếu bạn muốn và nó hoạt động tốt:

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;

Chỉnh sửa (vâng, khác):

Tôi vừa thấy câu hỏi đã sửa đổi của bạn (bị đóng là trùng lặp hoặc rất giống với câu hỏi này).

Nếu sự hiểu biết của tôi là đúng (postgres có tbla và dbtest có tblb và bạn muốn chèn từ xa với chọn cục bộ , không phải chọn từ xa với chèn cục bộ như trên):

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

Tôi không thích dblink lồng nhau đó, nhưng AFAIK, tôi không thể tham chiếu đến tblB trong phần thân dblink_exec . Sử dụng LIMIT để chỉ định 20 hàng trên cùng, nhưng tôi nghĩ bạn cần sắp xếp chúng bằng mệnh đề ORDER BY trước.


1
Cám ơn phản hồi của bạn. Chà, một câu hỏi nhanh nữa ... INSERT INTO tblA SELECT id, time FROM dblink('dbname=dbtest', 'SELECT id, time FROM tblB') AS t(id integer, time integer) WHERE time > 1000; Tôi có thể đưa ra một tuyên bố đã chuẩn bị sẵn về vấn đề này không?
Mayank

Xin chào @ grzegorz-szpetkowski, Logic này gây ra lỗi: LỖI: yêu cầu mật khẩu CHI TIẾT: Người không phải là người dùng cấp cao phải cung cấp mật khẩu trong chuỗi kết nối.
Neel Darji

34

Nếu bạn muốn chèn vào cột chỉ định:

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

9

Bạn có thể sử dụng dblink để tạo dạng xem được phân giải trong cơ sở dữ liệu khác. Cơ sở dữ liệu này có thể nằm trên một máy chủ khác.


Cảm ơn vi đa trả lơi. Nhưng tôi không hiểu cách INSERT INTO ... (SELECT FROM ...)sử dụng dblink sẽ hoạt động như thế nào . Những gì tôi cần là INSERT INTO ...được chạy trong phiên dblink tới Máy chủ DB khác, nhưng (SELECT FROM ...)trong phiên hiện tại của tôi.
Mayank

Bạn chỉ cần xác định tblA là dạng xem được hỗ trợ bởi dblink. Vì vậy, việc chèn, cập nhật, xóa sẽ được thực hiện trong cơ sở dữ liệu khác. dblink không chỉ đọc.
Hendrik Brummermann

9

Ký hiệu này (lần đầu tiên nhìn thấy ở đây ) cũng hữu ích:

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

2
Điều này chỉ hoạt động khi các bảng nằm trong cùng một cơ sở dữ liệu. Câu hỏi liên quan đến việc sao chép dữ liệu từ một bảng trong một cơ sở dữ liệu khác .
Nitin Nain


1

Đây là một giải pháp thay thế, không cần sử dụng dblink.

Giả sử B đại diện cho cơ sở dữ liệu nguồn và A đại diện cho cơ sở dữ liệu đích:

  1. Sao chép bảng từ DB nguồn sang DB đích:

    pg_dump -t <source_table> <source_db> | psql <target_db>
  2. Mở lời nhắc psql, kết nối với target_db và sử dụng một lệnh đơn giản insert:

    psql
    # \c <target_db>;
    # INSERT INTO <target_table>(id, x, y) SELECT id, x, y FROM <source_table>;
  3. Cuối cùng, hãy xóa bản sao của source_table mà bạn đã tạo trong target_table .

    # DROP TABLE <source_table>;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.