web-dev-qa-db-ja.com

シリアル主キー列を使用してテーブルの名前を安全に変更します

SERIAL主キーを使用するPostgreSQLテーブルは、PostgreSQLによって作成される暗黙のインデックス、シーケンス、および制約で終わることを知っています。問題は、テーブルの名前が変更されたときに、これらの暗黙的なオブジェクトの名前を変更する方法です。以下は、最後に特定の質問をしてこれを理解しようとする私の試みです。

次のようなテーブルがあるとします。

_CREATE TABLE foo (
    pkey SERIAL PRIMARY KEY,
    value INTEGER
);
_

Postgresの出力:

注意:CREATE TABLEは、シリアル列「foo.pkey」の暗黙的なシーケンス「foo_pkey_seq」を作成します
注意:CREATE TABLE/PRIMARY KEYは、テーブル「foo」の暗黙的なインデックス「foo_pkey」を作成します
クエリが正常に返され、52ミリ秒で結果が得られませんでした。

pgAdmin III SQLペインには、テーブルの次のDDLスクリプトが表示されます(デクラッタリング)。

_CREATE TABLE foo (
  pkey serial NOT NULL,
  value integer,
  CONSTRAINT foo_pkey PRIMARY KEY (pkey )
);
ALTER TABLE foo OWNER TO postgres;
_

テーブルの名前を変更します:

_ALTER table foo RENAME TO bar;
_

クエリは正常に返され、17ミリ秒で結果が得られませんでした。

pgAdmin III:

_CREATE TABLE bar (
  pkey integer NOT NULL DEFAULT nextval('foo_pkey_seq'::regclass),
  value integer,
  CONSTRAINT foo_pkey PRIMARY KEY (pkey )
);
ALTER TABLE bar OWNER TO postgres;
_

余分なDEFAULT nextval('foo_pkey_seq'::regclass),に注意してください。これは、テーブルの名前を変更しても主キーのシーケンスの名前が変更されないことを意味しますが、この明示的なnextval()があります。

シーケンスの名前を変更します:

データベースの名前の一貫性を保ちたいので、次のことを試しました。

_ALTER SEQUENCE foo_pkey_seq RENAME TO bar_pkey_seq;
_

クエリは正常に返され、17ミリ秒で結果が得られませんでした。

pgAdmin III:

_CREATE TABLE bar (
  pkey serial NOT NULL,
  value integer,
  CONSTRAINT foo_pkey PRIMARY KEY (pkey )
);
ALTER TABLE bar OWNER TO postgres;
_

DEFAULT nextval('foo_pkey_seq'::regclass),はなくなりました。

質問

  1. DEFAULT nextval('foo_pkey_seq'::regclass)ステートメントが表示されたり消えたりしたのはなぜですか?
  2. テーブルの名前を変更し、同時に主キーシーケンスの名前を変更する方法はありますか?
  3. クライアントがデータベースに接続しているときにテーブルの名前を変更してからシーケンスを実行しても安全ですか?同時実行の問題はありますか?
  4. Postgresはどのシーケンスを使用するかをどのように知るのですか?内部で使用されているデータベーストリガーはありますか?テーブルとシーケンス以外に名前を変更するものはありますか?
  5. 主キーによって作成された暗黙のインデックスはどうですか?名前を変更する必要がありますか?もしそうなら、それはどのように行うことができますか?
  6. 上記の制約名はどうですか?まだ_foo_pkey_です。制約の名前はどのように変更されますか?
20
ams

serialは実際のデータ型ではありません。 マニュアルの状態

データ型smallserialserial、およびbigserialは真の型ではなく、一意の識別子列を作成するための表記上の便宜にすぎません。

疑似データ型は、次のすべてを実行して解決されます。

  • _tablename_colname_seq_という名前のシーケンスを作成します

  • タイプinteger(またはsmallserial/bigserialの場合はそれぞれ_int2_/_int8_)の列を作成します

  • 列をNOT NULL DEFAULT nextval('tablename_colname_seq')にします

  • 列にシーケンスを所有させて、自動的に削除されるようにします

システムは、これをすべて手動で行ったか、疑似データ型serialを使用して行ったかを認識しません。 pgAdminはリストされた機能をチェックし、すべてが満たされている場合、リバースエンジニアリングされたDDLスクリプトは一致するserialタイプで簡略化されます。機能の1つが満たされない場合、この単純化は行われません。それはpgAdminが行うことです。基礎となるカタログテーブルについては、すべて同じです。 serialタイプ自体はありません。

所有しているシーケンスの名前を自動的に変更する方法はありません。実行できます:

_ALTER SEQUENCE ... RENAME TO ...
_

あなたがしたように。システム自体はnameを気にしません。列DEFAULTOID (_'foo_pkey_seq'::regclass_)を格納し、それを壊さずにシーケンスの名前を変更できます-OIDは同じままです。データベース内の外部キーや同様の参照についても、同じことが言えます。

主キーの暗黙的なインデックスは、PK制約の名前にバインドされます。これは、テーブルの名前を変更しても変更されませんPostgres 9.2以降では使用できます

_ALTER TABLE ... RENAME CONSTRAINT ..
_

それを修正するためにも。

テーブル名を参照して名前が付けられたインデックスもあります。 同様の手順

_ALTER INDEX .. RENAME TO  ..
_

テーブル名へのあらゆる種類の非公式な参照を持つことができます。システムは、好きな名前を付けることができるオブジェクトの名前を強制的に変更することはできません。そしてそれは気にしません。

もちろん、これらの名前を参照するSQLコードを無効にする必要はありません。明らかに、アプリケーションロジックが名前を参照している間は名前を変更したくありません。通常、インデックス、シーケンス、または制約の名前は通常名前で参照されないため、これは問題にはなりません。

Postgresは、オブジェクトの名前を変更する前に、オブジェクトのロックも取得します。したがって、問題のオブジェクトに対して何らかのロックが設定されている同時トランザクションが開いている場合、それらのトランザクションがコミットされるまで、RENAME操作は停止します。またはロールバックします。

システムカタログとOID

データベーススキーマは、システムスキーマ_pg_catalog_のシステムカタログのテーブルに格納されます。 ここにマニュアルのすべての詳細があります。 自分が何をしているのか正確にわからない場合は、これらのテーブルをいじってはいけません。 1つの誤った動きで、データベースを壊す可能性があります。 Postgresが提供するDDLコマンドを使用します。

最も重要なテーブルのいくつかについて、Postgresは オブジェクト識別子タイプ と型キャストを提供してOIDの名前を取得し、その逆も同様です。

_SELECT 'foo_pkey_seq'::regclass
_

スキーマ名が_search_path_にあり、テーブル名が一意である場合、次のようになります。

_SELECT oid FROM pg_class WHERE relname = 'foo_pkey_seq';
_

ほとんどのカタログテーブルの主キーはoidであり、内部的には、ほとんどの参照はOIDを使用します。

34