Postgres INSERT INTO ... SELECT违反外键约束

时间:2017-06-19 23:26:40

标签: database postgresql

我对postgres有一个非常非常奇怪的问题。我正在尝试为我的数据库中的业务对象生成GUID,并且我正在使用新的架构。我已经用几个业务对象完成了这项工作;我在这里使用的代码已经过测试,并在其他场景中有效。

这里是新表的定义:

CREATE TABLE guid.public_obj
(
  guid uuid NOT NULL DEFAULT uuid_generate_v4(),
  id integer NOT NULL,
  CONSTRAINT obj_guid_pkey PRIMARY KEY (guid),
  CONSTRAINT obj_id_fkey FOREIGN KEY (id)
      REFERENCES obj (obj_id)
      ON UPDATE CASCADE ON DELETE CASCADE
)

但是,当我尝试使用以下代码回填时,我得到一个SQL状态23503,声称我违反了外键约束。

INSERT INTO guid.public_obj (guid, id)
SELECT uuid_generate_v4(), o.obj_id
FROM obj o;

ERROR: insert or update on table "public_obj" violates foreign key constraint "obj_id_fkey"
SQL state: 23503
Detail: Key (id)=(-2) is not present in table "obj".

但是,如果我在源表上执行SELECT,则该值肯定存在:

SELECT uuid_generate_v4(), o.obj_id
FROM obj o
WHERE obj_id = -2;

"0f218286-5b55-4836-8d70-54cfb117d836";-2

当我将这个值直接从相应的表中拉出来时,我感到困惑的是为什么postgres会认为我违反了fkey约束。源表定义中对obj_id的唯一约束是它是主键。它被定义为一个序列; select将其作为整数返回。请帮忙!

1 个答案:

答案 0 :(得分:1)

好吧,显然这是失败的原因是因为我不知道桌子(我强调,它不包含许多元素)被分区。如果我执行SELECT COUNT(*) FROM obj;它返回348,但是如果我执行SELECT COUNT(*) FROM ONLY obj;它返回44.因此,有两个问题:首先,表中的一些数据没有被正确分区(那里在父表中存在未分区的数据),其次,我感兴趣的数据被分割出多个子表,并且父表上的fkey约束失败,因为数据实际上不在父表中。 (请注意,这不是我的架构;我必须使用已经存在很长时间的东西。)

分区是通过隐式类型(有三个分区,每个分区包含与obj的特定子类型相关的行),我认为最终的解决方案是为每个子类型创建GUID表。我将不得不处理实际上在obj表中的东西,可能是将它选入临时表,从obj表中删除行,然后重新插入它们以便可以正确分区。