更改Postgres中的列类型会导致pg_attrdef警告

时间:2018-02-26 16:04:03

标签: sql postgresql hibernate

我们正在尝试将numeric(10,2)列类型更改为numeric(17,2)类型。当我们用天真的方法做到这一点时:

ALTER TABLE table_a ALTER COLUMN col_a SET DATA TYPE numeric(17,2);

我们收到警告,我们不明白:

WARNING:  1 attrdef record(s) missing for rel table_a
WARNING:  generating possibly-non-unique OID for "pg_attrdef"

列类型确实已正确更改为numeric(17,2)(至少\d table_a告诉我们),我看不出结果表有什么问题,但警告仍然存在。

我们的表定义类似于:

                         Table "public.table_a"
         Column          |          Type          | Collation | Nullable | Default
-------------------------+------------------------+-----------+----------+---------
 col_a                   | numeric(10,2)          |           | not null | 0.00

在查阅postgres文档后,我们首先删除了Default约束,然后尝试了另一个列:

ALTER TABLE table_a ALTER COLUMN col_b DROP DEFAULT;
ALTER TABLE table_a ALTER COLUMN col_b SET DATA TYPE numeric(17,2);
ALTER TABLE table_a ALTER COLUMN col_b SET DEFAULT 0.00; 

导致更多警告:

WARNING:  2 attrdef record(s) missing for rel table_a
WARNING:  generating possibly-non-unique OID for "pg_attrdef"

正如您在另一列上运行查询后所看到的,我们现在在pg_attrdef中缺少2条记录。 在运行查询时,警告似乎会持续存在并随机显示。

我们检查了pg_attrdef表,看看我们是否能够发现:location内部表示中adbin字段已设置为-1的任何内容:

adrelid | 37294
adnum   | 37
adbin   | {FUNCEXPR :funcid 1703 :funcresulttype 1700 :funcretset false :funcvariadic false :funcformat 2 :funccollid 0 :inputcollid 0 :args ({CONST :consttype 1700 :consttypmod -1 :constcollid 0 :constlen -1 :constbyval false :constisnull false :location -1 :constvalue 6 [ 24 0 0 0 0 -127 ]} {CONST :consttype 23 :consttypmod -1 :constcollid 0 :constlen 4 :constbyval true :constisnull false :location -1 :constvalue 4 [ 6 0 17 0 0 0 0 0 ]}) :location -1}
adsrc   | 0.00

但用以下方法编译:

select pg_get_expr(pa.adbin, 'table_a'::regclass) from pg_attrdef pa where adrelid = 37294 and adnum = 37;

工作并返回正确的0.00值。

一些进一步的背景信息:该表由Hibernate生成,列定义如下:

@Column(nullable = false, columnDefinition = "Decimal(10,2) default '0.00'")
private Double col_a = 0.0;

我正在PostreSQL 10.0 DB上运行查询,但希望稍后在8.4 DB上运行它。

有人可以帮助我们弄清楚这些警告的含义以及我们如何避免这些警告?

1 个答案:

答案 0 :(得分:0)

服务器上的pg_catalog.attrdef表发生了一些事情,因此缺少attrdef的oid列上应该存在的唯一索引。

您可以在此处看到警告https://github.com/postgres/postgres/blob/master/src/backend/catalog/catalog.c#L312

我读到它是因为您发出的语句正在尝试设置默认值,因此它们正在写入attrdef表。 Postgres有一个内置的假设,即目录表将在oid列上具有唯一索引,并在缺少某个索引时输出警告。我无法在我的v10盒子上重新创建,所以我认为有人已经删除了特定实例上的唯一索引。

似乎缺少的索引称为“pg_attrdef_oid_index”,因此如果pg_catalog.pg_class中没有这个,则会出现问题。

除了您所看到的警告之外,可能没有任何后果。

尼尔