使用debian的Postgres10.4.2(实际上,使用postgresql docker容器)
我有一些模式文件,我申请顺序。它们创建、删除和更改表,以跟踪模式随时间的变化。
然后,运行一个程序,该程序从PGYCub目录中选择表定义,以生成现有表的代码包装器。到目前为止,这个方法还不错。(这个程序的代码是由我开发的,因此非常可疑!)
我最近将“alter table customer add field customer_stem varchar(255)not null default'”和“create index on customer(customer_stem)”添加到一个新的模式文件中。
现在,在查找主键的表的查询中不再找到customer表。
我运行的查询是:
select c.relname, i.indkey
from pg_catalog.pg_index i
inner join pg_catalog.pg_class c
on i.indrelid=c.relfilenode
inner join pg_catalog.pg_tables t
on c.relname=t.tablename
where t.schemaname='public'
and i.indisprimary;
这应该告诉我哪些索引是表的主键。
然而,“customer”表现在从这个查询中掉了出来——pg_类中的
relfilenode
不再匹配pg_索引中的任何内容。# select relname, relfilenode from pg_catalog.pg_class where relname='customer';
relname | relfilenode
----------+-------------
customer | 16512
observe_dev=# select count(1) from pg_catalog.pg_index where indrelid=16512;
count
-------
0
(1 row)
这个表应该有一个主键和一个辅助索引!
所以,我的猜测是,“alter table”语句以某种方式改变了“customer”类的ID,使得它不再匹配“pg_index”表,但这看起来真的很奇怪。PSQL仍然知道定义是什么:
Table "public.customer"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
---------------+------------------------+-----------+----------+-----------------------+----------+--------------+-------------
customer_id | integer | | not null | | plain | |
customer_name | character varying(255) | | not null | | extended | |
customer_stem | character varying(255) | | not null | ''::character varying | extended | |
Indexes:
"customer_pkey" PRIMARY KEY, btree (customer_id)
"customer_customer_name_idx" btree (customer_name)
"customer_customer_stem_idx" btree (customer_stem)
Referenced by:
还有一些外交关键关系。
所以,有两件事正在发生:
1)alter表以某种方式导致pg_目录停止保持最新(这似乎不太可能)
2)我对如何查找每个表的主键列的研究是错误的,而且我在查找错误的表/列
很有可能是2),但如果是,我应该如何找到这些信息?
最佳答案
我认为您应该加入pg_index
专栏,即:
select c.relname, i.indkey
from pg_catalog.pg_index i
inner join pg_catalog.pg_class c
on i.indrelid=c.oid -- << HERE change c.relfilenode to c.oid
left join pg_catalog.pg_tables t
on c.relname=t.tablename
where t.schemaname='public'
and i.indisprimary;
注意
pg_class.oid
对oid
和select * from pg_catalog.pg_class
在\d pg_catalog.pg_class
中的输出是隐藏的,但它是以“隐藏”列的形式存在的。我能够在本地复制您的问题,所以我猜添加列或索引会更改表的
psql
记录中relfilenode
的值。另请参见https://wiki.postgresql.org/wiki/Retrieve_primary_key_columns其中详细说明了如何查询主键-可能需要在join中添加到
pg_class
。不过,我发现值得注意的是,PostgreSQL将pg_attribute
转换成了适当的'my_table_name'::regclass
。实际上,您可以通过运行pg_class.oid
来测试(并获取任何表的oid
)!为了方便起见,我还做了一些进一步的测试,以确定是哪个表更改触发了
select 'my_table_name'::regclass::oid
更改。原因似乎是默认的“pg_class.relfilenode
”。添加列而不指定
alter table add column ...
时,该值保持不变。以下脚本演示了该行为:create table test (id uuid, col1 varchar(255));
select c.oid, c.relfilenode, c.relname from pg_catalog.pg_class c where c.oid = 'test'::regclass;
alter table test add column col2 varchar(255) not null;
select c.oid, c.relfilenode, c.relname from pg_catalog.pg_class c where c.oid = 'test'::regclass;
alter table test add column col3 varchar(255) not null default '';
select c.oid, c.relfilenode, c.relname from pg_catalog.pg_class c where c.oid = 'test'::regclass;
drop table test;
因此,添加具有默认值的列似乎会由于某种原因更改关系的filenode。有关
default
和其他属性的更多详细信息,也值得阅读PostgreSQL docs on pg_class
。关于sql - 为什么我的表从pg_catalog.pg_class中消失了? (或者,如何查找主键列?),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51886387/