sql - 使用新列将主键从简单更改为复合
问题描述
我正在尝试将我的一个表的主键从简单键更改为复合键,其中复合键应由旧的 pk 列和新创建的列组成。
我从一个非常相似的问题中遵循了这个答案:https ://stackoverflow.com/a/27832197/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_
和组成的新复合 pk version_
。这是我的脚本:
-- 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_
null。的对应值Catalog.version_
正确设置为 1。
我的错误在哪里?我是否还必须CatalogEntry.catalog_version_
手动设置为 1?我会假设它会自动设置。
解决方案
的值CatalogEntry.catalog_version_
不会因为您定义了外键约束而神奇地设置。
实际发生的是没有行 inCatalogEntry
引用Catalog
. 原因是外键约束的默认值是MATCH SIMPLE
,请参阅文档:
MATCH SIMPLE
允许任何外键列为空;如果其中任何一个为空,则该行不需要在引用的表中具有匹配项。
您应该创建外键约束,MATCH FULL
以便所有列或所有列都必须为 NULL。然后您会收到创建外键的错误。
解决方案:在那里更新CatalogEntry
并将列设置为 1,然后使用MATCH FULL
.
推荐阅读
- sql-server - SSRS 报告给多值参数错误
- java - 我可以写一个没有“这个”字的课程吗
- python - 在python中使用xpath查询从以下节点中选择整个文本以及子节点
- spring-batch - 春季批处理表
- c# - 如何将 WPF 图像 + 形状刻录到新图像
- javascript - 如何使在 JavaFX 的 Java 类中解析的 JSON 对象被使用/通信/发送到 Javascript?
- c# - 查看复选框下方的复选框内容都可见吗?
- reactjs - react中根据props引用一张图片
- javascript - 为什么不使用“hiddengrid:true”就不会将数据输出到jqGrid?
- php - Wordpress:如果将 html/php 混合到帖子中,则插入块的最佳实践