所以我试图解决这个问题,但是似乎最后一行(判断)不允许在其中进行子查询.有没有办法让这件事变得像甲骨文一样有效?

CREATE TABLE Tank (
    n_id            int,
    day             date,
    level           int,
    CONSTRAINT pk_w_td PRIMARY KEY (n_id,day),
    CONSTRAINT fk_w_td_tan FOREIGN KEY (n_id) REFERENCES Tanks ON DELETE CASCADE,
    CHECK (level > 0 AND level <= (SELECT capacity FROM Tanks WHERE Tanks.n_id = TanksDay.n_id))
);

以下是错误信息:

Error at Command Line:7 Column:32 Error report: SQL Error: ORA-02251: subquery not allowed here
02251. 00000 -  "subquery not allowed here"
*Cause:    Subquery is not allowed here in the statement.
*Action:   Remove the subquery from the statement.

推荐答案

有三种基本方法可以解决这类问题,因为判断约束不能基于查询.

Option 1: Triggers

最简单的方法是在坦克上设置一个触发器,该触发器查询坦克,并在液位超过容量时抛出异常.然而,这种简单化方法的问题是,几乎不可能正确处理并发问题.如果会话1降低了容量,那么会话2提高了级别,然后两个事务都提交,触发器将无法检测到违规行为.如果其中一个或两个表很少修改,这可能不是问题,但总的来说,这将是一个问题.

Option 2: Materialized views

通过创建联接TANK和TANKS表的提交时实体化视图,然后在验证级别=容量的实体化视图上创建CHECK约束条件,可以解决并发性问题.通过使实体化视图仅包含会违反约束的数据,还可以避免存储两次数据.这将需要两个基表上的materialized 视图日志(log),这将增加插入的一些开销(尽管比使用触发器要少).将判断推到提交时间将解决并发性问题,但会引入一些异常管理问题,因为现在提交操作可能会因为实例化视图刷新失败而失败.您的应用程序需要能够处理该问题,并提醒用户注意这一事实.

Option 3: Change the data model

如果表A中的值依赖于表B中的限制,这可能表示B中的限制应该是表A的属性(而不是表B的属性,或者作为表B的属性之外的属性).当然,这取决于您的数据模型的具体情况,但通常是值得考虑的.

Database相关问答推荐

在MongoDB的树形 struct 中更新具有给定id的元素

Postgresql 服务器:允许访问私有网络内的远程连接,而不是外部网络

如何在华为Appcube中创建和使用对象(模型)?

将数据集上传到 Hub 时停止运行时会导致什么?

Mongodb聚合$group,限制数组长度

为什么 COUNT() 只显示一行表格?

存储所有排列的模式数据库

什么是 Scalar标量查询?

:force => true 在模式文件中是什么意思

是否可以在ORDER BY子句之后放置任何可能造成安全风险的内容?

什么是表前缀?

我应该使用 NULL 还是空字符串来表示表列中没有数据?

判断Android中的应用程序数据库中是否存在列

数据完整性和数据一致性之间有什么区别吗?

如果表不存在,如何使用 Derby Db 创建表

将 .csv 文件导入 Android 中的 Sqlite

PostgreSQL 唯一索引和字符串大小写

PHP PDO: error number' 00000' when query is correct

在两列之间 Select 最近的日期

获取 xp_cmdshell 的执行权限