94

postgres テーブルがあります。そこからいくつかのデータを削除する必要があります。一時テーブルを作成し、データをコピーし、インデックスを再作成し、必要な行を削除するつもりでした。この元のテーブルがデータのソースであるため、元のテーブルからデータを削除できません。ある場合には X の削除に依存する結果を得る必要があり、別の場合には Y を削除する必要があります。

ただし、テーブルを再作成して再度コピーし、インデックスを再作成するのは少しばかげているようです。「構造、データ、およびインデックスを含む、このテーブルの完全な個別のコピーが必要です」と通知するためにpostgresにとにかくありますか?

残念ながら、PostgreSQL には「CREATE TABLE .. LIKE X INCLUDING INDEXES」がありません。

4

6 に答える 6

114

新しい PostgreSQL ( docs によると 8.3 以降) は、「INCLUDING INDEXES」を使用できます。

# select version();
                                             version
-------------------------------------------------------------------------------------------------
 PostgreSQL 8.3.7 on x86_64-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu3)
(1 row)

ご覧のとおり、私は 8.3 でテストしています。

それでは、テーブルを作成しましょう。

# create table x1 (id serial primary key, x text unique);
NOTICE:  CREATE TABLE will create implicit sequence "x1_id_seq" for serial column "x1.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "x1_pkey" for table "x1"
NOTICE:  CREATE TABLE / UNIQUE will create implicit index "x1_x_key" for table "x1"
CREATE TABLE

そして、それがどのように見えるかを見てください:

# \d x1
                         Table "public.x1"
 Column |  Type   |                    Modifiers
--------+---------+-------------------------------------------------
 id     | integer | not null default nextval('x1_id_seq'::regclass)
 x      | text    |
Indexes:
    "x1_pkey" PRIMARY KEY, btree (id)
    "x1_x_key" UNIQUE, btree (x)

これで、構造をコピーできます。

# create table x2 ( like x1 INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES );
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "x2_pkey" for table "x2"
NOTICE:  CREATE TABLE / UNIQUE will create implicit index "x2_x_key" for table "x2"
CREATE TABLE

そして構造をチェックしてください:

# \d x2
                         Table "public.x2"
 Column |  Type   |                    Modifiers
--------+---------+-------------------------------------------------
 id     | integer | not null default nextval('x1_id_seq'::regclass)
 x      | text    |
Indexes:
    "x2_pkey" PRIMARY KEY, btree (id)
    "x2_x_key" UNIQUE, btree (x)

8.3 より前の PostgreSQL を使用している場合は、オプション「-t」を指定して pg_dump を使用するだけで、1 つのテーブルを指定し、ダンプ内のテーブル名を変更して、再度ロードすることができます。

=> pg_dump -t x2 | sed 's/x2/x3/g' | psql
SET
SET
SET
SET
SET
SET
SET
SET
CREATE TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE

そして今、テーブルは次のとおりです。

# \d x3
                         Table "public.x3"
 Column |  Type   |                    Modifiers
--------+---------+-------------------------------------------------
 id     | integer | not null default nextval('x1_id_seq'::regclass)
 x      | text    |
Indexes:
    "x3_pkey" PRIMARY KEY, btree (id)
    "x3_x_key" UNIQUE, btree (x)
于 2009-07-03T12:34:33.243 に答える
48
[CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name
    [ (column_name [, ...] ) ]
    [ WITH ( storage_parameter [= value] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
    [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
    [ TABLESPACE tablespace ]
    AS query][1]  

ここに例があります

CREATE TABLE films_recent AS
  SELECT * FROM films WHERE date_prod >= '2002-01-01';

最初から新しいテーブルを作成する別の方法は、使用することです

    CREATE TABLE films_recent (LIKE films INCLUDING INDEXES);  

    INSERT INTO films_recent
         SELECT *
           FROM books
          WHERE date_prod >= '2002-01-01';  

2 番目の方法を使用した場合、Postgresql にはテーブルスペースの問題を修正するためのパッチが適用されていることに注意してください。

于 2008-10-13T20:01:30.740 に答える
4

postgres テーブルがあります。そこからいくつかのデータを削除する必要があります。

私はそれを推測します...

delete from yourtable
where <condition(s)>

・・・なぜかうまくいきません。(その理由を共有してもよろしいですか?)

一時テーブルを作成し、データをコピーし、インデックスを再作成し、必要な行を削除するつもりでした。

pg_dump と pg_restore を調べます。いくつかの巧妙なオプションで pg_dump を使用し、おそらく pg_restoring の前に出力を編集するとうまくいくかもしれません。


データに対して「what if」タイプの分析を行っているので、ビューを使用した方がよいのではないでしょうか。

除外したいものの否定に基づいて、テストしたいシナリオごとにビューを定義できます。つまり、含めたいものに基づいてビューを定義します。たとえば、X=Y の行を「削除」したデータの「ウィンドウ」が必要な場合は、(X != Y) の行としてビューを作成します。

ビューは、定義クエリとしてデータベース (システム カタログ) に保存されます。ビューにクエリを実行するたびに、データベース サーバーはそれを定義する基礎となるクエリを検索し、それを実行します (使用した他の条件との AND 演算)。このアプローチにはいくつかの利点があります。

  1. データのいかなる部分も複製することはありません。
  2. 各ビュー/シナリオにクエリを実行すると、ベース テーブル (元の「実際の」テーブル) に既に使用されているインデックスが使用されます (クエリ オプティマイザーによって適切と判断された場合)。それらを再定義またはコピーする必要はありません。
  3. ビューはベース テーブルの「実際の」データに対する「ウィンドウ」(スナップショットではない) であるため、ベース テーブルを追加/更新/削除し、ビュー シナリオを再クエリするだけで何も再作成する必要はありません。データは時間とともに変化します。

もちろん、トレードオフがあります。ビューは仮想テーブルであり、「実際の」(ベース)テーブルではないため、アクセスするたびに(おそらく複雑な)クエリを実際に実行しています。これにより、動作が少し遅くなる場合があります。しかし、そうではないかもしれません。多くの問題 (データのサイズと性質、システム カタログの統計の品質、ハードウェアの速度、使用負荷など) によって異なります。試してみないとわかりません。パフォーマンスが許容できないほど遅いことが実際にわかった場合 (およびその場合にのみ)、他のオプションを検討することもできます。(実体化されたビュー、テーブルのコピーなど、スペースと時間を交換するもの。)

于 2008-10-13T20:29:52.807 に答える
2

簡単な方法は、すべてを含めることです。

CREATE TABLE new_table (LIKE original_table INCLUDING ALL);
于 2019-06-20T19:04:24.197 に答える
1

選択を使用して新しいテーブルを作成し、必要なデータを取得します。次に、古いテーブルを新しいテーブルと交換します。

create table mynewone as select * from myoldone where ...
mess (re-create) with indexes after the table swap.
于 2008-10-13T16:33:31.223 に答える