20

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です。制約の名前はどのように変更されますか?
4

1 に答える 1

34

serial実際のデータ型ではありません。マニュアルには次のように記載されています

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

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

  • 名前の付いたシーケンスを作成しますtablename_colname_seq

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

  • 列を作るNOT NULL DEFAULT nextval('tablename_colname_seq')

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

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

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

ALTER SEQUENCE ... RENAME TO ...

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

主キーの暗黙的なインデックスは、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を使用することです。

于 2013-02-01T17:29:03.013 に答える