postgresql: ВСТАВИТИ У… (SELECT *…)


124

Я не впевнений, чи є його стандартний 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.

EDIT:
Якщо це неможливо, я б пішов на вилучення значень з 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

Відповіді:


151

Як писав Генрік, ви можете використовувати 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, Ця логіка дає помилку: ПОМИЛКА: пароль необхідний ДЕТАЛЬНО: Несуператори повинні вказати пароль у рядку з'єднання.
Ніл Дарджи

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, але (SELECT FROM ...)в моєму поточному сеансі.
Mayank

Ви просто визначите tblA як перегляд, який підтримується dblink. Тож вставлення, оновлення, видалення будуть виконані в іншій базі даних. dblink не читається тільки.
Гендрік Бруммерман

9

Ця позначення (вперше помічена тут ) також виглядає корисною:

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

2
Це працює лише тоді, коли таблиці знаходяться в одній базі даних. Питання стосується копіювання даних із таблиці в іншу базу даних .
Нітін Найн


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>;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.