【问题标题】:Is there a way to create a constraint that applies both on the table and when it's constraint is effected by a change on another table?有没有办法创建一个既适用于表又适用于它的约束受另一个表的更改影响的约束?
【发布时间】:2022-10-13 01:11:22
【问题描述】:

我有一个案例,我想做一个复杂的约束检查,我的表中引用的外键根据该表中的另一个值而变化。它可能不是最好的实现,但由于技术债务太多,我无法改变它。目前我们没有约束检查,这可能会导致问题,我的意图是解决这个问题,而不是重做整个数据库,即使那是理想的。

这是我的案例的抽象:

CREATE TABLE VehicleType (
    vehicletypeid integer primary key,
    vehicletypename varchar not null,
    pktablename varchar,
    pkcolumnname varchar
);
CREATE TABLE Car (carid integer primary key, carname varchar);
CREATE TABLE Truck (truckid integer primary key, truckname varchar);
CREATE TABLE VehicleColourOptions (
    vehicletypeid integer REFERENCES VehicleType(vehicletypeid),
    vehicleid integer,
    colourid integer REFERENCES colouroptions(colourid)
);
INSERT INTO VehicleType (vehicletypeid, vehicletypename, pktablename, pkcolumnname) VALUES
(1, 'Car', 'Car', 'carid'), (2, 'Truck', 'Truck', 'truckid');
/* Also need values in Car and Truck tables and a colouroptions table*/

也可能有两种以上的类型。

我知道我可以在添加或更新期间为 VehicleColourOptions 表添加一个触发约束,这将触发一个函数,该函数将使用 VehicleColourOptions vehicletypeid 来确定要查询哪个表以检查具有给定车辆标识的该类型的值是否存在pktablename 和 pkcolumnname。我还没有编写这个函数,但对它的可行性很有信心。

担心的是反向约束将不存在,换句话说,如果删除 Car 行或进行某些修改以删除受约束的 carid,除非我们在 Car 和 Truck 表的 DELETE 上添加 TRIGGER CONSTRAINT,否则不会进行检查在逆中具有相同类型的函数。问题是,如果车辆抽象以类似于 VehicleColourOptions 的方式在多个不同的表中使用,则需要使用 vehicletype-vehicleid 模式为每个表再次更新该函数。

还有其他方法可以解决这个问题吗?

辅助问题

除了无法使用 fk 约束之外,不应该以这种方式构建表的充分理由是什么?我可以想到优点,主要是可扩展性,因此用户可以将任何类型与任何类型相关联。我上面的抽象并没有做到这个用例公正,因为可能没有用例来关联汽车和卡车,但在我的工作中,类型概念用于许多不同的事物,从词汇到位置再到对象,我们有许多不同的关联表。

还有一个好处是后端代码可以非常简单。如果我想要一个 UI 让用户将车辆与颜色选项相关联,我只需要提供一个后端服务,该服务将从 VehicleColourOptions 表中进行 CRUD。如果我有 CarColourOptions 和 TruckColourOptions 表,这将变得更加复杂。并不是说我不愿意投入工作,而是在我编写后端时这很好。

【问题讨论】:

  • 我不明白你的模型和你想要做什么,但你知道你可以对你的外键有一个规则吗?示例:... 外键 (...) 更新 <action> 上删除 <action>。动作可以设置为空、级联、限制,可能还有更多,请查看您的 DBMS 的文档

标签: sql postgresql


【解决方案1】:

我完全不确定您将要做什么,但我猜您正在尝试实现某种“子类型”?如果是这种情况,典型的模式是:

CREATE TABLE vehicle_type
( vehicletype_id INT NOT NULL PRIMARY KEY
, vehicletype_name VARCHAR(?) NOT NULL 
);

CREATE TABLE vehicle
( vehicle_id INT NOT NULL PRIMARY KEY -- could you use a natural identifier such as VIN or licence plate?
, vehicletype_id INT NOT NULL
      REFERENCES vehicle_type (vehicletype_id)
, ...
, CONSTRAINT ak_vehicle UNIQUE (vehicletype_id, vehicle_id)
);

CREATE TABLE car
( vehicle_id INT NOT NULL PRIMARY KEY
, vehicletype_id INT NOT NULL
, ...
, CONSTRAINT fk_vehicle_type FOREIGN KEY (vehicletype_id, vehicle_id)
, CONSTRAINT ck_car CHECK (vehicletype_id = 1) -- assuming car is type 1
);

现在,fk fk_vehicle_type 确保 car 具有与父车辆相同的 vehicle_type,并且检查约束 ck_car 确保只有汽车可以具有 car 类型。

【讨论】:

    猜你喜欢
    • 2013-11-26
    • 2019-10-14
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 2017-02-14
    • 2020-12-03
    相关资源
    最近更新 更多