将主键从简单更改为与新列组合

epggiuax  于 2021-07-26  发布在  Java
关注(0)|答案(1)|浏览(454)

我正在尝试将我的一个表的主键从简单改为复合键,复合键应该由旧的pk列和新创建的pk列组成。
我从一个非常相似的问题中得出了这个答案:https://stackoverflow.com/a/27832197/1948454
它几乎可以工作,只是在从属表中没有为新列设置值。
情况如下:
假设我有一个目录表和一个目录条目表。之前:

  1. -- DDL Catalog
  2. CREATE TABLE public.Catalog (
  3. name_ VARCHAR(255) NOT NULL,
  4. foo_ VARCHAR(255) NULL,
  5. CONSTRAINT Catalog_pkey PRIMARY KEY (name_)
  6. );
  7. -- DDL CatalogEntry
  8. CREATE TABLE public.CatalogEntry (
  9. pricekey_ VARCHAR(255) NOT NULL,
  10. pricekeyroot_ VARCHAR(255) NOT NULL,
  11. catalog_name_ VARCHAR(255) NULL,
  12. bar_ VARCHAR(255) NULL,
  13. CONSTRAINT CatalogEntry_pkey PRIMARY KEY (pricekey_, pricekeyroot_)
  14. );
  15. -- public.CatalogEntry FOREIGN KEYs
  16. 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 表,指示某个目录的版本。这意味着我必须创建一个新的复合pk,由 name_ 以及 version_ . 这是我的剧本:

  1. -- UPDATE script
  2. -- add the new version column and set all values to default of 1
  3. ALTER TABLE Catalog ADD version_ INTEGER;
  4. UPDATE Catalog SET version_ = 1;
  5. ALTER TABLE Catalog ALTER column version_ SET not null;
  6. -- update primary key and foreign key
  7. BEGIN;
  8. -- first, drop fkey constraint on CatalogEntry
  9. ALTER TABLE CatalogEntry DROP CONSTRAINT CatalogEntry_catalog_name__fkey;
  10. -- then, update Catalog primary key
  11. ALTER TABLE Catalog DROP CONSTRAINT Catalog_pkey,
  12. ADD CONSTRAINT Catalog_uni_name UNIQUE (name_),
  13. ADD PRIMARY KEY (name_, version_);
  14. -- now add new foreign key again to CatalogEntry
  15. ALTER TABLE CatalogEntry ADD catalog_version_ INTEGER;
  16. ALTER TABLE CatalogEntry
  17. ADD CONSTRAINT CatalogEntry_catalog_name__catalog__fkey FOREIGN KEY (catalog_name_, catalog_version_)
  18. references Catalog(name_, version_ ) ON DELETE CASCADE;
  19. COMMIT;
  20. -- finally, remove unique constraint on name since it is not needed anymore
  21. ALTER TABLE Catalog DROP CONSTRAINT Catalog_uni_name;

执行这些步骤后,主键和外键似乎设置正确—但是 CatalogEntry.catalog_version_ 为空。的对应值 Catalog.version_ 正确设置为1。
我的错在哪里?我也要设置吗 CatalogEntry.catalog_version_ 手动设置为1?我会假设它会自动设置。

yhxst69z

yhxst69z1#

价值 CatalogEntry.catalog_version_ 不会仅仅因为定义了外键约束就神奇地设置。
实际上发生的是没有争吵 CatalogEntry 引用中的行 Catalog . 原因是外键约束的默认值是 MATCH SIMPLE ,请参阅文档: MATCH SIMPLE 允许任何外键列为空;如果其中任何一个为空,则不要求该行在引用的表中具有匹配项。
您应该将外键约束创建为 MATCH FULL 因此所有列或所有列都必须为null。那么您在创建外键时就会收到一个错误。
解决方案:更新 CatalogEntry 并将列也设置为1,然后用 MATCH FULL .

相关问题