12

単体テストの目的で一時テーブルをセットアップしようとしています。これまでのところ、既存のテーブルの構造をコピーする一時テーブルを作成できました。

CREATE TEMP TABLE t_mytable (LIKE mytable INCLUDING DEFAULTS);

しかし、これには元のテーブルのデータがありません。CREATE TABLE AS代わりにステートメントを使用して、データを一時テーブルにコピーできます。

CREATE TEMP TABLE t_mytable AS SELECT * FROM mytable;

ただし、t_mytable列のサイズとデフォルト値が異なるなど、構造は同一ではありません。すべてをコピーする単一のステートメントはありますか?

使用する最初のクエリのもう 1 つの問題LIKEは、キー列がまだSEQUENCE元のテーブルの を参照しているため、挿入時に増加することです。独自のシーケンスで新しいテーブルを作成する簡単な方法はありますか?それとも新しいシーケンスを手動で設定する必要がありますか?

4

2 に答える 2

10

Postgres 10 以降

Postgres 10 では、SQL 標準に準拠したIDENTITY列が導入されました (マイナーな拡張機能付き)。テーブルの ID 列は次のようになります。

id    integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY

マニュアルの構文。従来の列
の代わりにこれを使用すると、シーケンスに関する問題が回避されます。列は、仕様が でコピーされた場合でも、排他的な専用シーケンスを自動的に使用します。マニュアル:serialIDENTITYLIKE

コピーされた列定義の ID 指定は、INCLUDING IDENTITYが指定されている場合にのみコピーされます。古いテーブルに関連付けられたシーケンスとは別に、新しいテーブルの ID 列ごとに新しいシーケンスが作成されます。

と:

INCLUDING ALLの省略形ですINCLUDING DEFAULTS INCLUDING IDENTITY INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE INCLUDING COMMENTS

解決策はより簡単になりました:

CREATE TEMP TABLE t_mytable (LIKE mytable INCLUDING ALL);
INSERT INTO t_mytable TABLE mytable;
SELECT setval(pg_get_serial_sequence('t_mytable', 'id'), max(id)) FROM tbl;

setval()示されているように、シーケンスの現在の値を設定するために引き続き使用できます。シングルSELECTはトリックを行います。pg_get_serial_sequence()] 6シーケンスの名前を取得します。

デシベル<>ここでフィドル

関連している:


元の(古い)回答

データベース ダンプまたはpgAdmin (データベース オブジェクト作成スクリプトをリバース エンジニアリングする)などの GUI から create スクリプトを取得し、同一のコピーを作成して (serial列のシーケンスを個別に)、次のコマンドを実行します。

INSERT INTO new_tbl
SELECT * FROM old_tbl;

両方のテーブルが同じスキーマに存在する場合、コピーを 100% 同一にすることはできません。明らかに、テーブル名は異なる必要があります。インデックス名も競合します。同じシーケンスからシリアル番号を取得することも、おそらく最善の利益にはなりません。したがって、(少なくとも) 名前を調整する必要があります。

コピーを別のスキーマに配置すると、これらの競合がすべて回避されます。デモのように通常のテーブルから一時テーブルを作成しますが、一時テーブルは独自の一時スキーマに存在するため、自動的に作成されます。

または、DDL コードを直接コピーするための Francisco の回答をご覧ください。

于 2012-09-04T14:07:17.963 に答える