Oracle检查约束与subquerys [exercise]

时间:2016-04-29 18:24:22

标签: sql oracle constraints

我想解决这个练习(应该是可以解决的)。 你有下表。该表包括座位预订,开始/结束之间的所有座位都被保留。

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

使用约束扩展此表定义,检查哪个地方不会保留两次。

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

2 个答案:

答案 0 :(得分: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值,实际上使表成为链表。所有约束协同工作以确保范围不重叠。

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