2016-04-29 299 views
3

我想解决这个问题(应该是可以解决的)。 您有下表。该表包括座位预留,保留了开始/结束日期之间的所有座位。用subquerys检查Oracle的限制[exercise]

CREATE TABLE reservation ( 
    owner CHAR(10) NOT NULL PRIMARY KEY, 
    start INTEGER NOT NULL, 
    end INTEGER NOT NULL 
) 

扩展这个表定义与约束什么检查,没有哪个地方会被保留两次。

据我所知,在检查约束中不可能使用子查询。那么我可以使用什么样的约束?

+1

,可以使用约束无法做到这一点。你需要一个trigger.stackoverflow.com/questions/8770552/can-i-have-a-constraint-on-count-of-distinct-values-in-a-column-in-sql –

+0

是的,这就是我所知道的,但我想知道这是否可能。 –

+0

你可以改变表格(添加更多列等)吗?如果是,那么是的,这是可能的。通过单独的DRI(FOREIGN KEY,UNIQUE和CHECK约束)使复杂但可能。 –

回答

3

这不能用单个CHECK约束来完成,因为它本质上是一个依赖表的多个行的约束。

它与某种方式的UNIQUE约束相似。在唯一约束中,没有两行可以具有相同的值。在这里,没有两行可以有重叠范围。所以,如果我们能够用检查重叠范围的条件替换平等条件(=),那就恰到好处。

在另一个DBMS(Postgres)中,实际上可以使用专有的EXCLUDE约束强制执行这个和类似的约束。


在Oracle现在有共同的FOREIGN KEYUNIQUECHECK限制其他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的值,从本质上使该表成为一个链表。所有限制条件一起工作以确保范围不重叠。

+0

其实我认为它也需要'UNIQUE(previous_end)'约束。我会引导并纠正。 –

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);