postgresql:INSERT INTO…(SELECT *…)


124

標準SQLかどうかはわかりません。

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

私が探しているのは、tblAとtblBが異なるDBサーバーにある場合です。

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ポニー、

回答:


151

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は好きではありませんが、私の知る限り、dblink_exec本体でtblBを参照できません。LIMITを使用して上位20行を指定しますが、最初にORDER BY句を使用してそれらをソートする必要があると思います。


1
御返答いただき有難うございます。さて、もう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


9

dblink使用して、別のデータベースで解決されるビューを作成できます。このデータベースは別のサーバー上にある可能性があります。


返信いただきありがとうございます。しかし、INSERT INTO ... (SELECT FROM ...)dblinkを使用してどのように機能するかわかりませんでした。必要なのはINSERT INTO ...、他のDBサーバーへのdblinkセッションで実行することですが(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. ソースDBからターゲットDBにテーブルをコピーします。

    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. 最後に、target_tableで作成したsource_tableのコピーを削除します。

    # DROP TABLE <source_table>;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.