问题描述
当我只有私钥时,我正在尝试对一行使用检查约束。我不知道是否有其他方法可以检查此类内容,我对 sql 还很陌生,所以我也乐于接受建议。
这是一个最小的例子:
我有以下表格:
Buildings:
building_id: int GENERATED PRIMARY KEY
Floors:
floor_id: int GENERATED PRIMARY KEY
floor_nr: int
building_id: int FOREIGN KEY REFERENCES Buildings (building_id)
Glasses:
glass_id: int GENERATED PRIMARY KEY
building_id: int FOREIGN KEY REFERENCES Buildings (building_id)
Floors_Glasses:
floor_id: int FOREIGN KEY REFERENCES Floors (floor_id)
glass_id: int FOREIGN KEY REFERENCES Glasses (building_id)
当我想将玻璃移到地板上时,我需要检查是否
(SELECT building_id FROM Floors WHERE floor_id = floor.floor_id) == glass.building_id
编辑:
我最终使用了如下约束触发器:
CREATE CONSTRAINT TRIGGER "trigger name"
AFTER UPDATE OF "column name" ON "table name"
FOR EACH ROW EXECUTE PROCEDURE "procedure name"
并引发异常
raise exception 'message' using errcode = 'restrict_violation';
解决方法
如果一个玻璃真的可以同时在多个楼层,将 building_id
添加到 floors_glasses
并从该表创建复合外键到 floors
和 glasses
包括 building_id
列。这将保证您的完整性约束。
您不能定义引用其他行或表的检查约束,因为一旦您修改这些其他对象,它就会变得无效。例如,还原转储可能会失败。
,您始终可以在应用级别强制执行此规则。然而,我总是不信任这些应用程序(因为它们总是充满错误),所以我个人更喜欢尽可能在数据库级别强制执行规则。
这需要更多的启动工作,但可以为您节省大量时间,因为它从一开始就可以防止数据损坏问题。
你可以这样做:
create table buildings (
building_id int primary key not null
);
create table floors (
building_id int not null references buildings (building_id),floor_id int not null,floor_nr int,primary key (building_id,floor_id)
);
create table glasses (
building_id int not null references buildings (building_id),glass_id int not null,glass_price int,glass_id)
);
create table floor_glasses (
building_id int not null,floor_id,glass_id),foreign key (building_id,floor_id) references floors (building_id,floor_id),glass_id) references glasses (building_id,glass_id)
);
关键概念在最后一个表格中。只有一个列building_id
用于两个外键引用。这种引用共享确保最后一个表中引用的地板和玻璃始终属于同一建筑物。