2017-06-19 76 views
1

我对postgres有一个非常非常奇怪的问题。我试图为我的数据库中的业务对象生成GUID,并且我正在为此使用新的模式。我已经用几个业务对象完成了这个工作;我在这里使用的代码已经过测试并在其他场景下工作。Postgres INSERT INTO ...选择违反外键约束

下面是新表的定义:

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

你是否保持你的模式是直的?我看到你的CREATE TABLE是在'guid'模式中创建的,但'obj'表使用默认模式。 ?? – pbuck

+0

'select relnamespace,relname from pg_class where relname ='obj';' –

+0

我有我的模式直,是的。我使用一个新的模式来保存所有的guid关系,因为需要guid的业务对象并不都在公共模式中。 – Gideon

回答

0

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

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