PostgreSQLテーブルから特定の行をINSERT SQLスクリプトとしてエクスポートする


196

という名前のデータベーススキーマnyummyと、次の名前のテーブルがありますcimory

create table nyummy.cimory (
  id numeric(10,0) not null,
  name character varying(60) not null,
  city character varying(50) not null,
  CONSTRAINT cimory_pkey PRIMARY KEY (id)
);

cimoryテーブルのデータを挿入SQLスクリプトファイルとしてエクスポートします。ただし、都市が「東京」に等しいレコード/データのみをエクスポートしたいと思います(都市データはすべて小文字であると想定しています)。

どうやってするの?

ソリューションがフリーウェアのGUIツールであるかコマンドラインであるかは関係ありません(ただし、GUIツールソリューションの方が優れています)。pgAdmin IIIを試しましたが、これを行うオプションが見つかりません。


2
INSERTステートメントをスキップして、データベース間で直接SELECTを使用してコピーできます。albertech.blogspot.com/2016/11/...

PostgreSQLはデータベース間で選択できません。少なくとも、古いバージョンはできませんし、Greenplumもできません。9.xについて知りません。
PhilHibbs 2017

私はこれが古い実現が、私はちょうどいることを言及したかったです使用してデータベース間で選択することが可能にdblinkの少なくともV8.3以降で利用可能です。外部サーバーと外部データラッパーを使用して、「リモート」データベースに接続します。これは、それらのデータベースが同じインスタンスに存在する場合でも、まったく異なるホストに存在する場合でも機能します。他のデータベースに具体化されたビューを作成して特定のレポート作成などを容易にするために、かなり広範囲に使用してきました。
G_Hosa_Phat

回答:


280

エクスポートするセットでテーブルを作成し、コマンドラインユーティリティpg_dumpを使用してファイルにエクスポートします。

create table export_table as 
select id, name, city
from nyummy.cimory
where city = 'tokyo'
$ pg_dump --table=export_table --data-only --column-inserts my_database > data.sql

--column-inserts 列名のある挿入コマンドとしてダンプします。

--data-only スキーマをダンプしません。

以下にコメントするように、テーブルの代わりにビューを作成すると、新しいエクスポートが必要な場合は常にテーブルの作成が不要になります。


3
さて、これまでのところあなたの解決策は機能しています。見落としているのは、「-U user_name」を追加する必要があることです。ToraSQLツールでもほぼ成功しています。スクリプトの結果の日時データにエラーがあるだけです。2日以内にGUIツールソリューションを提供できない人がいれば、回答は受け入れられ
ます

2
他の人と共有したい場合は、無料のGUIツールであるSQL Workbench / J(postgreSQL jdbc4ドライバーを使用)を使用して、同じことを行うこともできます。
null

1
これはcreate view export_view...、ベーステーブルへの変更によってビューが最新の状態に保たれるため、を使用した方がはるかに優れています。ドキュメントは言う--table=table: Dump only tables (or **views**...私は、これは仕事といくつかの希望を持っていたので、残念ながらビューをダンプしてもデータが得られていません。:P
2016年

@poshest 9.5で動作します。正確には何を試しましたか?
Clodoaldo Neto

@ClodoaldoNetoああ、よかった!私もそれを動作させることができると思います。私pg_dump --table=my_schema.my_view --data-only --inserts my_db > data.sqlはバージョン9.5.3 を使用しましたが、私のcreate説明はあなたのものと同じでしたcreate view...。出力で得られるのは、通常のpg_dumpコメントとSETステートメントだけです。どこが間違っているのかわからない。
最高級の

176

以下のためのデータのみのエクスポートを使用COPY。コマンド
行ではなくプレーンテキストとして1行に1つのテーブル行を含むファイルを取得します。ファイルはINSERT小さくて高速です。

COPY (SELECT * FROM nyummy.cimory WHERE city = 'tokio') TO '/path/to/file.csv';

次のものを使用して、同じものを同じ構造の別のテーブルにインポートします。

COPY other_tbl FROM '/path/to/file.csv';

COPY書き込みやファイルの読み取り、サーバーへのローカルのようなクライアントプログラムとは異なり、pg_dumpまたはpsql読み取りおよび書き込みは、ファイルをクライアントにローカル。両方が同じマシンで実行される場合、それは重要ではありませんが、リモート接続の場合はそうです。

以下\copyのようなpsqlコマンドもあります。

フロントエンド(クライアント)コピーを実行します。これはSQL COPYコマンドを実行する操作ですが、サーバーが指定されたファイルを読み書きする代わりに、psqlはファイルを読み書きし、サーバーとローカルファイルシステム間でデータをルーティングします。つまり、ファイルのアクセス可能性と権限はサーバーではなくローカルユーザーのものであり、SQLスーパーユーザー権限は必要ありません。


10
OPは、挿入SQLスクリプトファイルとしてデータを特別に呼び出します。彼はinsertコマンドについて話していると思いませんか?
Clodoaldo Neto 2012年

1
@Clodoaldo:あなたは正しいかもしれませんが、その場合、あなたの答えはよりふさわしいでしょう。作成スクリプトをpgAdminに個別にコピーすることもできます(OPがGUIについて言及しているように)。
Erwin Brandstetter 2012年

3
STDINまたSTDOUT、ファイルパスの代わりに使用でき、小規模なデータのエクスポートに役立ちます。
Amir Ali Akbari

1
なし--column-insertsフラグ、pg_dumpは使用COPYが生成SQLコードのテーブルのそれぞれについて、STDINから。
Randall

2
SELECTする列の順序が宛先データベースの列の順序と一致するように注意してください。そうでない場合、これは失敗するか、またはさらに悪いことに成功しますが、不良データが挿入されます。
ネイサンウォレス

32

これは、追加のインストールなしで手動でpgAdmin使用してテーブルをスクリプトエクスポートする簡単かつ迅速な方法です

  1. ターゲットテーブルを右クリックし、[バックアップ]を選択します。
  2. バックアップを保存するファイルパスを選択します。形式として「プレーン」を選択します。
  3. 下部にある[ダンプオプション#2]タブを開き、[列の挿入を使用]をオンにします。
  4. [バックアップ]ボタンをクリックします。
  5. 結果のファイルをテキストリーダー(たとえば、notepad ++)で開くと、テーブル全体を作成するスクリプトが表示されます。そこから、生成されたINSERTステートメントを単にコピーできます。

このメソッドは、@ Clodoaldo Netoの回答に示されているように、export_tableを作成する手法でも機能します。

ターゲットテーブルを右クリックして[バックアップ]を選択します

宛先パスを選択し、フォーマットを「プレーン」に変更します

下部にある[ダンプオプション#2]タブを開き、[列の挿入を使用]をオンにします

そこからINSERTステートメントをコピーできます。


これを行うと、「Bakckup」オプションがありません。これはpgAdmin III v1.18.1であり、Greenplum 4.3.4.1(PostgreSQL 8.2.15に基づく)に接続しています。
PhilHibbs 2017

pgAdmin III v1.18.1をインストールしました、「バックアップ」オプションがありました。PostgreSQL 9.5に接続しました。したがって、問題はおそらくpgAdminとGreenplumの間です。
アンディR

pgAdmin4で意図したとおりに機能する
Nikhil

9

SQL Workbenchにはそのような機能があります。

クエリを実行した後、クエリ結果を右クリックし、[SQLとしてデータをコピー> SQL挿入]を選択します。


1
それは素晴らしい働きをします。「ドライバー」として「postgres」を選択した場合は、JDBCドライバーを自分でダウンロードする必要がある可能性があります。jdbc.postgresql.org / download.html (.jarファイル-javaバイナリです) postgresql接続の「ドライバー」。接続文字列(またはインターフェースのURL)は次のようになります
。jdbc

DBVisualizerには、ファイルにコピーしたり、クリップボードに直接コピーしたりできる、同様の優れた機能があります。
Noumenon 2017年

8

私のユースケースでは、単純にgrepにパイプすることができました。

pg_dump -U user_name --data-only --column-inserts -t nyummy.cimory | grep "tokyo" > tokyo.sql

2
他の分野で「東京」を持つことを検討する必要があります。
Buyut Joko Rivai

@BuyutJokoRivaiこれはほとんどの場合テーブルのみのダンプなので問題ないはずです
Ismail Iqbal

ケース<3のなかで最も賢い方法
Nam G VU

大きなテーブルを使用しても、ソリューションの落とし穴であるgrepのすべての行をダンプします。その後、としてここにダンプするテーブルへの道私たちのクエリとストア結果stackoverflow.com/a/12816187/248616はよりsuiteableある
ナムG VU

5

@PhilHibbsコードに基づいて、別の方法でそれを行うプロシージャを記述しようとしました。ご覧になってテストしてください。

 CREATE OR REPLACE FUNCTION dump(IN p_schema text, IN p_table text, IN p_where text)
   RETURNS setof text AS
 $BODY$
 DECLARE
     dumpquery_0 text;
     dumpquery_1 text;
     selquery text;
     selvalue text;
     valrec record;
     colrec record;
 BEGIN

     -- ------ --
     -- GLOBAL --
     --   build base INSERT
     --   build SELECT array[ ... ]
     dumpquery_0 := 'INSERT INTO ' ||  quote_ident(p_schema) || '.' || quote_ident(p_table) || '(';
     selquery    := 'SELECT array[';

     <<label0>>
     FOR colrec IN SELECT table_schema, table_name, column_name, data_type
                   FROM information_schema.columns
                   WHERE table_name = p_table and table_schema = p_schema
                   ORDER BY ordinal_position
     LOOP
         dumpquery_0 := dumpquery_0 || quote_ident(colrec.column_name) || ',';
         selquery    := selquery    || 'CAST(' || quote_ident(colrec.column_name) || ' AS TEXT),';
     END LOOP label0;

     dumpquery_0 := substring(dumpquery_0 ,1,length(dumpquery_0)-1) || ')';
     dumpquery_0 := dumpquery_0 || ' VALUES (';
     selquery    := substring(selquery    ,1,length(selquery)-1)    || '] AS MYARRAY';
     selquery    := selquery    || ' FROM ' ||quote_ident(p_schema)||'.'||quote_ident(p_table);
     selquery    := selquery    || ' WHERE '||p_where;
     -- GLOBAL --
     -- ------ --

     -- ----------- --
     -- SELECT LOOP --
     --   execute SELECT built and loop on each row
     <<label1>>
     FOR valrec IN  EXECUTE  selquery
     LOOP
         dumpquery_1 := '';
         IF not found THEN
             EXIT ;
         END IF;

         -- ----------- --
         -- LOOP ARRAY (EACH FIELDS) --
         <<label2>>
         FOREACH selvalue in ARRAY valrec.MYARRAY
         LOOP
             IF selvalue IS NULL
             THEN selvalue := 'NULL';
             ELSE selvalue := quote_literal(selvalue);
             END IF;
             dumpquery_1 := dumpquery_1 || selvalue || ',';
         END LOOP label2;
         dumpquery_1 := substring(dumpquery_1 ,1,length(dumpquery_1)-1) || ');';
         -- LOOP ARRAY (EACH FIELD) --
         -- ----------- --

         -- debug: RETURN NEXT dumpquery_0 || dumpquery_1 || ' --' || selquery;
         -- debug: RETURN NEXT selquery;
         RETURN NEXT dumpquery_0 || dumpquery_1;

     END LOOP label1 ;
     -- SELECT LOOP --
     -- ----------- --

 RETURN ;
 END
 $BODY$
   LANGUAGE plpgsql VOLATILE;

その後 :

-- for a range
SELECT dump('public', 'my_table','my_id between 123456 and 123459'); 
-- for the entire table
SELECT dump('public', 'my_table','true');

混合フィールドのデータ型(テキスト、double、int、タイムスタンプなしのタイムスタンプなど)を含むテーブルを使用して、私のpostgres 9.1でテストしました。

そのため、TEXTタイプのCASTが必要です。私のテストは約900万行で正しく実行されましたが、実行の18分前に失敗したようです。

ps:WEBでmysqlに相当するものを見つけました。


3

特定のレコードでテーブルを表示し、SQLファイルをダンプできます

CREATE VIEW foo AS
SELECT id,name,city FROM nyummy.cimory WHERE city = 'tokyo'

3
pgAdmin IIIで試してみましたが、Viewオブジェクトにはダンプするオプションがありません。
null

navicatを試してください。私はそれを使用しており、SQLスクリプトのエクスポートオプションがあります
Giorgi Peikrishvili

@ Giorgi:フリーウェア版はありますか?
null

Postgres 9.1を使用することはできません
HCarrasko

2

私はこれを行うための簡単な手順をたたきました。これは単一の行に対してのみ機能するため、必要な行を選択するだけの一時的なビューを作成し、pg_temp.temp_viewを挿入先の実際のテーブルに置き換えます。

CREATE OR REPLACE FUNCTION dv_util.gen_insert_statement(IN p_schema text, IN p_table text)
  RETURNS text AS
$BODY$
DECLARE
    selquery text; 
    valquery text; 
    selvalue text; 
    colvalue text; 
    colrec record;
BEGIN

    selquery := 'INSERT INTO ' ||  quote_ident(p_schema) || '.' || quote_ident(p_table);

    selquery := selquery || '(';

    valquery := ' VALUES (';
    FOR colrec IN SELECT table_schema, table_name, column_name, data_type
                  FROM information_schema.columns 
                  WHERE table_name = p_table and table_schema = p_schema 
                  ORDER BY ordinal_position 
    LOOP
      selquery := selquery || quote_ident(colrec.column_name) || ',';

      selvalue := 
        'SELECT CASE WHEN ' || quote_ident(colrec.column_name) || ' IS NULL' || 
                   ' THEN ''NULL''' || 
                   ' ELSE '''' || quote_literal('|| quote_ident(colrec.column_name) || ')::text || ''''' || 
                   ' END' || 
        ' FROM '||quote_ident(p_schema)||'.'||quote_ident(p_table);
      EXECUTE selvalue INTO colvalue;
      valquery := valquery || colvalue || ',';
    END LOOP;
    -- Replace the last , with a )
    selquery := substring(selquery,1,length(selquery)-1) || ')';
    valquery := substring(valquery,1,length(valquery)-1) || ')';

    selquery := selquery || valquery;

RETURN selquery;
END
$BODY$
  LANGUAGE plpgsql VOLATILE;

このようにして呼び出されました:

SELECT distinct dv_util.gen_insert_statement('pg_temp_' || sess_id::text,'my_data') 
from pg_stat_activity 
where procpid = pg_backend_pid()

私はこれをインジェクション攻撃に対してテストしていません。quote_literalの呼び出しでは不十分であるかどうかをお知らせください。

また、:: textに単純にキャストして再度戻すことができる列に対してのみ機能します。

これはGreenplum用でもありますが、Postgres、CMIIWで動作しない理由は考えられません。


-2

" EXECUTE QUERY WRITE RESULT TO FILE " オプションで クエリを実行するpgadminを試してみました

それはデータをエクスポートするだけです、そうでなければ

pg_dump -t view_name DB_name > db.sql

==>に使用する-tオプション一致するテーブル(またはビューまたはシーケンス)のみをダンプします。参照


1
これはcreate viewステートメントのみをエクスポートします
cdmckay
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.