在检查约束中使用查询
Using queries in check constraints
我试图对一行使用检查约束,而我只有私钥。我不知道是否有其他方法可以检查此类内容,我是 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
并创建从 table 到 floors
的复合外键和glasses
包括 building_id
列。这将保证您的完整性约束。
您不能定义引用其他行或 table 的检查约束,因为一旦您修改这些其他对象,它就会失效。例如,恢复转储可能会失败。
您始终可以在应用级别强制执行此规则。但是,我总是不信任这些应用程序(因为它们总是充满错误),所以我个人更喜欢尽可能在数据库级别执行规则。
它需要更多的启动工作,但可以在以后为您节省大量时间,因为它从一开始就防止了数据损坏问题。
你可以这样做:
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,
primary key (building_id, glass_id)
);
create table floor_glasses (
building_id int not null,
floor_id int not null,
glass_id int not null,
primary key (building_id, floor_id, glass_id),
foreign key (building_id, floor_id) references floors (building_id, floor_id),
foreign key (building_id, glass_id) references glasses (building_id, glass_id)
);
关键概念在最后table。在 two 外键引用中只使用了 one 列 building_id
。此 引用共享 可确保最后 table 中引用的楼层和玻璃始终属于同一建筑物。
我试图对一行使用检查约束,而我只有私钥。我不知道是否有其他方法可以检查此类内容,我是 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
并创建从 table 到 floors
的复合外键和glasses
包括 building_id
列。这将保证您的完整性约束。
您不能定义引用其他行或 table 的检查约束,因为一旦您修改这些其他对象,它就会失效。例如,恢复转储可能会失败。
您始终可以在应用级别强制执行此规则。但是,我总是不信任这些应用程序(因为它们总是充满错误),所以我个人更喜欢尽可能在数据库级别执行规则。
它需要更多的启动工作,但可以在以后为您节省大量时间,因为它从一开始就防止了数据损坏问题。
你可以这样做:
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,
primary key (building_id, glass_id)
);
create table floor_glasses (
building_id int not null,
floor_id int not null,
glass_id int not null,
primary key (building_id, floor_id, glass_id),
foreign key (building_id, floor_id) references floors (building_id, floor_id),
foreign key (building_id, glass_id) references glasses (building_id, glass_id)
);
关键概念在最后table。在 two 外键引用中只使用了 one 列 building_id
。此 引用共享 可确保最后 table 中引用的楼层和玻璃始终属于同一建筑物。