Sql 使用新列将主键从简单更改为复合
我正在尝试将我的一个表的主键从简单改为复合键,复合键应该由旧的pk列和新创建的pk列组成 我从一个非常相似的问题中得出了这个答案: 它几乎可以工作,只是在Dependent表中没有为新列设置值 情况如下: 假设我有一个目录表和一个目录条目表。之前:Sql 使用新列将主键从简单更改为复合,sql,postgresql,primary-key,composite-primary-key,Sql,Postgresql,Primary Key,Composite Primary Key,我正在尝试将我的一个表的主键从简单改为复合键,复合键应该由旧的pk列和新创建的pk列组成 我从一个非常相似的问题中得出了这个答案: 它几乎可以工作,只是在Dependent表中没有为新列设置值 情况如下: 假设我有一个目录表和一个目录条目表。之前: -- DDL Catalog CREATE TABLE public.Catalog ( name_ VARCHAR(255) NOT NULL, foo_ VARCHAR(255) NULL, CONSTRAINT Cat
-- 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\u name
引用了catalog.name\u
现在,我需要在目录
表中添加另一列version
,指示某个目录的版本。这意味着我必须创建一个新的组合主键,由name\u
和version\u
组成。这是我的剧本:
-- 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\u version\uu
的值为空。目录.版本的相应值已正确设置为1
我的错在哪里?我是否也必须手动将
CatalogEntry.catalog\u version\u设置为1?我假设它会自动设置。CatalogEntry.catalog\u版本的值不会因为定义外键约束而神奇地设置
实际情况是,CatalogEntry
中没有任何行引用Catalog
中的行。原因是外键约束的默认值为MATCH SIMPLE
,请参见:
MATCH SIMPLE
允许任何外键列为空;如果其中任何一个为空,则该行不需要在引用的表中具有匹配项
您应该将外键约束创建为MATCH FULL
,以便所有列或所有列都必须为NULL。那么您将收到一个创建外键的错误
解决方案:更新CatalogEntry
,并在此处将列设置为1,然后使用MATCH FULL
定义外键。非常感谢您的解释和解决方案。