作成したテストテーブルwith主キーが主キーを返さないというやや複雑なシナリオがあります。 pgAdmin IIIは、制約がないと報告しています。 PostgreSQLクエリログ全体があり、以下にテストテーブルの作成に使用したクエリがあります。次に、主キーを別のテストテーブルにドロップし、生成されたクエリ(手動で実行したクエリではありません)を使用して、pgAdmin IIIを検索し、問題のテーブルに主キーをドロップしましたが、何も検索されませんでした。
ALTER TABLE public.delete_key_bigserial DROP CONSTRAINT
文字列「DROPCONSTRAINT」は、テストテーブルを作成する数週間前の2014-12-02にさかのぼるクエリログに1回だけ表示されます。主キーがbigserial
またはserial
に設定されている場合とされていない場合があり、主キーのIDを整数に設定してからid
を設定せずにテーブルを作成したこともわかりました。主キーになります(全日のワームの別の缶)。
以前の質問 でdata_type
を取得する方法について質問しました。これには、ErwinBrandstetterが優れた回答をしたbigserial
またはserial
のどちらであるかが含まれます。彼は特に2つのクエリを提供しました。1つはすべての列のdata_type
sをフェッチし、もう1つは主キーのdata_type
をフェッチします。残念ながら、私がテストしてきたテストテーブルの1つは、結果を返していません。
SELECT a.attrelid::regclass::text, a.attname,
CASE a.atttypid
WHEN 'int'::regtype THEN 'serial'
WHEN 'int8'::regtype THEN 'bigserial'
WHEN 'int2'::regtype THEN 'smallserial'
END AS serial_type
FROM pg_attribute a
JOIN pg_constraint c ON c.conrelid = a.attrelid AND c.conkey[1] = a.attnum
JOIN pg_attrdef ad ON ad.adrelid = a.attrelid
AND ad.adnum = a.attnum
WHERE a.attrelid = 'delete_key_bigserial'::regclass
AND a.attnum > 0
AND NOT a.attisdropped
AND a.atttypid = ANY('{int,int8,int2}'::regtype[]) -- integer type
AND c.contype = 'p' -- PK
AND array_length(c.conkey, 1) = 1 -- single column
AND ad.adsrc = 'nextval('''
|| (pg_get_serial_sequence (a.attrelid::regclass::text, a.attname))::regclass
|| '''::regclass)';
クエリは他のすべてのテーブルで完全に機能します。
私は2014年11月からPostgreSQLと2011年頃からMySQLを使用しているだけなので、AFAIKでできる最善のことは、できるだけ多くの関連データをフェッチすることです。クエリログからdelete_key_bigserial
テーブルを作成するために使用されるクエリは次のとおりです。
CREATE TABLE public.delete_key_bigserial (id bigserial PRIMARY KEY NOT NULL)
WITH (OIDS = FALSE);
Erwinのクエリを簡略化し、テーブルで使用して、クエリツールの結果を、クエリが完全に正常に機能するさまざまなテストテーブルと比較しました(4つのdata_type
sすべて)。
SELECT * FROM pg_attribute a
WHERE a.attrelid = 'delete_key_bigserial'::regclass
AND a.attnum > 0
AND NOT a.attisdropped
AND attname='id'
ORDER BY a.attnum;
+----------+---------+----------+---------------+--------+--------+----------+-------------+
| attrelid | attname | atttypid | attstattarget | attlen | attnum | attndims | attcacheoff |
+----------+---------+----------+---------------+--------+--------+----------+-------------+
| 46390 | id | 20 | -1 | 8 | 20 | 0 | -1 |
+----------+---------+----------+---------------+--------+--------+----------+-------------+
+-----------+----------+------------+----------+------------+-----------+--------------+
| atttypmod | attbyval | attstorage | attalign | attnotnull | atthasdef | attisdropped |
+-----------+----------+------------+----------+------------+-----------+--------------+
| -1 | f | p | d | t | t | f |
+-----------+----------+------------+----------+------------+-----------+--------------+
+------------+-------------+--------------+--------+------------+---------------+
| attislocal | attinhcount | attcollation | attacl | attoptions | attfdwoptions |
+------------+-------------+--------------+--------+------------+---------------+
| t | 0 | | | | |
+------------+-------------+--------------+--------+------------+---------------+
Erwinは、他の条件が満たされたときにatttypid
列を介してタイプを導出していますが、結果の列/行は、機能する他のテーブルと同じです。主キーのdata_type
が何であるかを判断するために使用した別のカタログテーブルがあるため、次のクエリを使用して、そのテーブルの結果も比較することにしました。
SELECT * FROM information_schema.columns
WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
AND table_name='delete_key_bigserial'
AND is_nullable='NO';
返された列/行(table_name
列とcolumn_default
列のテーブル名を除く)の唯一の違いは、dtd_identifier
列でした。テーブルdelete_key_bigserial
は、値dtd_identifier
の列20
を返します。作業テーブルの場合、クエリは1
を返します。 (の下部) PostgreSQL element_typesドキュメント は列を次のように説明します:
要素のデータ型記述子の識別子。これは現在役に立ちません。
これは、単に説明自体を参照することはできますが、レガシー目的のために保持されている非推奨/古いファッションだと思いますか?よくわかりませんが、ここが私がいる場所であり、正しい道を進んでいるとさえ確信していません。
私はむしろ問題に対処し、シナリオから学び、それがテストテーブルであるという理由だけでそれを無視したいと思います。ある日、この問題がテストであるときに対処しなければならないと確信していますnotテーブル。問題が何であるかを追跡するのに役立つ可能性のある関連情報で質問を更新させていただきます。
このように作成されたテーブルの場合:
CREATE TABLE public.delete_key_bigserial (id bigserial PRIMARY KEY NOT NULL);
... 前の回答の両方のクエリ (およびpgAdmin、psql、またはその他の適切なクライアント)はPK制約を見つけます。そこにない場合は、なんとかして削除しました。
最初のクエリは、PKおよびserial
タイプの場合にのみ列を返すことに注意してください。これは例の場合です。
混乱のもう1つの考えられる原因:データベースにdelete_key_bigserial
という名前のテーブルが複数ある可能性がありますか?テーブル名は、単一のスキーマ内でのみ一意です。テスト:
SELECT * FROM pg_class WHERE relname = 'delete_key_bigserial';
クエリを明確にするには、テーブル名をスキーマ修飾します。
WHERE a.attrelid = 'public.delete_key_bigserial'::regclass
ログにDROP CONSTRAINT
を残さずに、制約を「非表示」にする方法があります。
log_statement
またはその他の関連する設定を設定します。contype = 'p'
で設定されます pg_constraint
。ログファイルを編集します。
等.