我想解决这个练习(应该是可以解决的)。 你有下表。该表包括座位预订,开始/结束之间的所有座位都被保留。
CREATE TABLE reservation (
owner CHAR(10) NOT NULL PRIMARY KEY,
start INTEGER NOT NULL,
end INTEGER NOT NULL
)
使用约束扩展此表定义,检查哪个地方不会保留两次。
据我所知,在检查约束中使用子查询是不可能的。那么我可以使用什么样的约束?
答案 0 :(得分:3)
使用单个CHECK
约束无法做到这一点,因为它本质上是一个依赖于表的多个行的约束。
它在某种程度上类似于UNIQUE
约束。在唯一约束中,没有两行可以具有相同的值。在这种情况下,没有两行可以具有重叠范围。因此,如果我们可以用检查重叠范围的条件替换相等条件(=
),那就恰到好处。
在另一个DBMS(Postgres)中,实际上可以使用专有的EXCLUDE
约束来强制执行此约束和类似约束。
在Oracle现在和其他具有常见FOREIGN KEY
,UNIQUE
和CHECK
约束的DBMS中,如果允许您通过添加更改表设计,实际上可能会很复杂另一栏:
CREATE TABLE reservation (
owner CHAR(10) NOT NULL PRIMARY KEY,
start INTEGER NOT NULL,
end INTEGER NOT NULL,
previous_end INTEGER NULL,
CONSTRAINT valid_range
CHECK (start <= end),
CONSTRAINT unique_end
UNIQUE (end),
CONSTRAINT previous_range_fk
FOREIGN KEY (previous_end)
REFERENCES reservation (end),
CONSTRAINT valid_previous
CHECK (previous_end < start)
) ;
我们很高兴。您只需正确提供previous_end
值,实际上使表成为链表。所有约束协同工作以确保范围不重叠。
答案 1 :(得分:0)
您可以使用物化视图解决此问题:
CREATE TABLE reservation (
owner CHAR(10) NOT NULL PRIMARY KEY,
"start" INTEGER NOT NULL,
"end" INTEGER NOT NULL
);
CREATE MATERIALIZED VIEW LOG ON reservation
WITH SEQUENCE, ROWID("start","end")
INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW reservation_MV
BUILD IMMEDIATE
REFRESH FAST ON COMMIT
AS SELECT "start" + LEVEL - 1 AS table_number
FROM reservation
CONNECT BY "start" + LEVEL - 1 <= "end";
ALTER TABLE reservation_MV ADD CONSTRAINT reservation__mv__pk
PRIMARY KEY ( table_number );