将主键从简单键更改为带有新列的复合键

问题描述 投票:1回答:1

我正在尝试将我的一个表的主键从简单键更改为组合键,其中组合键应由旧的pk列和新创建的键组成。

我从一个非常相似的问题回答了这个答案:https://stackoverflow.com/a/27843468/1948454

几乎可以工作,除了在依赖表中没有为新列设置值。

这里是情况:

假设我有一个用于目录的表和一个用于目录条目的表。之前:

-- DDL Catalog

CREATE TABLE public.Catalog (
    name_ VARCHAR(255) NOT NULL,
    foo_ VARCHAR(255) NULL,
    CONSTRAINT Catalog_pkey PRIMARY KEY (name_)
);

-- DDL CatalogEntry

CREATE TABLE public.CatalogEntry (
    pricekey_ VARCHAR(255) NOT NULL,
    pricekeyroot_ VARCHAR(255) NOT NULL,
    catalog_name_ VARCHAR(255) NULL,
    bar_ VARCHAR(255) NULL,
    CONSTRAINT CatalogEntry_pkey PRIMARY KEY (pricekey_, pricekeyroot_)
);    

-- public.CatalogEntry FOREIGN KEYs

ALTER TABLE public.CatalogEntry ADD CONSTRAINT CatalogEntry_catalog_name__fkey FOREIGN KEY (catalog_name_) REFERENCES Catalog(name_) ON DELETE CASCADE;

因此CatalogEntry.catalog_name引用了Catalog.name_

现在我需要在version_表中添加另一列Catalog,以指示某些目录的版本。这意味着我将必须创建一个由name_version_组成的新合成pk。这是我的脚本:

-- UPDATE script

-- add the new version column and set all values to default of 1
ALTER TABLE Catalog ADD version_ INTEGER;
UPDATE Catalog SET version_ = 1;
ALTER TABLE Catalog ALTER column version_ SET not null;

-- update primary key and foreign key
BEGIN;
-- first, drop fkey constraint on CatalogEntry
ALTER TABLE CatalogEntry DROP CONSTRAINT CatalogEntry_catalog_name__fkey;
-- then, update Catalog primary key
ALTER TABLE Catalog DROP CONSTRAINT Catalog_pkey,
    ADD CONSTRAINT Catalog_uni_name UNIQUE (name_),
    ADD PRIMARY KEY (name_, version_);
-- now add new foreign key again to CatalogEntry
ALTER TABLE CatalogEntry ADD catalog_version_ INTEGER;
ALTER TABLE CatalogEntry 
    ADD CONSTRAINT CatalogEntry_catalog_name__catalog__fkey FOREIGN KEY (catalog_name_, catalog_version_) 
        references Catalog(name_, version_ ) ON DELETE CASCADE;
COMMIT;

-- finally, remove unique constraint on name since it is not needed anymore
ALTER TABLE Catalog DROP CONSTRAINT Catalog_uni_name;

执行这些步骤后,主键和外键似乎已正确设置-但CatalogEntry.catalog_version_的值为空。 Catalog.version_的相应值已正确设置为1。

我的错误在哪里?我还必须手动将CatalogEntry.catalog_version_设置为1吗?我本以为会自动设置它。

sql postgresql primary-key composite-primary-key
1个回答
0
投票

CatalogEntry.catalog_version_的值不会仅仅因为您定义了外键约束而神奇地设置了。

实际上发生的是CatalogEntry中的no行引用了Catalog中的行。原因是外键约束的默认值为MATCH SIMPLE,请参见the documentation

MATCH SIMPLE允许任何外键列为空;如果它们中的任何一个为null,则不需要该行在引用表中具有匹配项。

您应将外键约束创建为MATCH FULL,以便所有列或所有列均不得为NULL。然后,您将在创建外键时收到错误消息。

解决方案:更新CatalogEntry并将该列也设置为1,然后用MATCH FULL定义外键。

© www.soinside.com 2019 - 2024. All rights reserved.