sql - 对相关表的约束
问题描述
我有 2 个表(ItemType 和 Item)。ItemType 有一个 boolean hasSize
,并且 Item 表有一个size
列。
我想强制size
仅在hasSize
boolean = true 时设置。
我已经看到讨论使用触发器进行验证的解决方案。但是,这并不能提供与约束相同的鲁棒性。
这是非理想模式设计的问题,还是有合适的解决方案?
解决方案
检查约束不能引用数据库中的其他表,触发器是解决此限制的有效策略。我不认为您的架构设计不好。某些类型的项目是相当大的,并且该信息属于item_type
表中。
这是不使用触发器的替代解决方案,其中我使用修饰符对UPDATABLE VIEW施加检查约束以防止基础表中的数据修改WITH CHECK OPTION
。请注意,这只会验证数据是否通过视图插入或更新。您必须授予适当的权限,以便应用程序角色不能item
直接修改表,但可以通过UPDATABLE VIEW
这是一个独立的脚本,其中包含示例数据和示例插入失败和插入成功
-- set up dummy `item_type` table
CREATE TABLE item_type (
id int primary key generated by default as identity,
has_size bool,
name text not null unique
);
INSERT INTO item_type
(has_size, name)
VALUES
(true, 'sizable type')
, (false, 'unisize');
-- set up dummy `item` table
CREATE TABLE item (
id int primary key generated by default as identity,
type_id int references item_type(id),
name text NOT NULL,
size text
);
INSERT INTO item
(type_id, name, size)
VALUES
(1, 'worlds best dad tee shirt', 'M')
, (2, 'usb key', NULL);
-- create updatable check view.
CREATE VIEW item_view AS
SELECT item.*
FROM item
WHERE EXISTS (
SELECT
FROM item_type
WHERE item.type_id = item_type.id
AND (item.size IS NOT NULL) = item_type.has_size
)
WITH CASCADED CHECK OPTION;
-- ^^^
-- i could have alternately used local
-- instead of cascaded
此插入将失败
INSERT INTO item_view
(type_id, name, size)
VALUES
(2, 'dad socks', 'M');
它会产生以下错误:
ERROR: new row violates check option for view "item_view"
DETAIL: Failing row contains (3, 2, dad socks, M).
此插入将成功
INSERT INTO item_view
(type_id, name, size)
VALUES
(2, 'dad socks', NULL);
SELECT * FROM item
按预期返回以下结果
id | type_id | name | size
----+---------+---------------------------+------
1 | 1 | worlds best dad tee shirt | M
2 | 2 | usb key |
4 | 2 | dad socks |
推荐阅读
- node.js - 为我的第一个 Angular 应用程序运行“ng serve”时出错
- mongodb - Jhipster Spring Boot 2 不同数据库上的微服务实例
- regex - 匹配全局,但仅当行以特定字符串开头时
- javascript - 如何使用 codeigniter 4 包含位于 node_modules 文件夹中的脚本?
- android - 如何在同一布局中创建指向元素的链接?
- azure-devops - 无法将同一集合两次导入 Azure DevOps Services
- electron - npm run make 在电子锻造中不起作用
- git - 远程:在 /home/kovair/git_home/OmnibusAdapterListener/Log4perl/lib/Log/Log4perl/Appender.pm 第 164 行的连接或字符串中使用未初始化的值
- android - 有没有办法在幕后工作以防止 ANR 在 Android 中长时间工作?
- javascript - 加速脚本 Gscript