关系数据库检查约束ORACLE

时间:2019-02-27 20:59:42

标签: sql oracle check-constraints

我正在为Uni进行项目,并且我对数据库没有太多的知识或经验。我试图在Oracle中使用表创建数据库,该表包含2种类型的制造零件,例如1和2。当零件类型为1时,我将在表中存储其位置,当类型2为I时。会将提前期存储在同一张表中。因此,在这两种情况下,我都会在另一列中使用空值(我知道使用空值的问题,但是在考虑了这个问题并研究了解决此问题的最佳方法之后,我决定这样做,因为我只有少量的属性)。我的问题是在检查约束中。我试图这样做:

CREATE TABLE manufactured (
PID INT NOT NULL,
PARTTYPE NUMBER (1) NOT NULL,
CHECK (PARTTYPE IN (1,2)),
CONSTRAINT REFMAN FOREIGN KEY (PID, PARTTYPE) REFERENCES PART (PID, PARTTYPE),
LOCATION VARCHAR (50),
CONSTRAINT LOC CHECK (PARTTYPE=1 AND LOCATION IS NOT NULL),
CONSTRAINT LOC2 CHECK(PARTTYPE=2 AND LOCATION IS NULL),
LEAD_TIME VARCHAR (50),
CONSTRAINT LEADTIME CHECK (PARTTYPE=2 AND LEAD_TIME IS NOT NULL),
CONSTRAINT LEADTIME2 CHECK (PARTTYPE=1 AND LEAD_TIME IS NULL),
CONSTRAINT PK_MAN PRIMARY KEY (PID));

这不起作用。

我试图插入一条记录,如下所示:

insert into manufactured(PID, PARTTYPE, LOCATION) values(101,1,'Warehouse1'); 

我得到了错误: ORA-02290:违反了检查约束(*****。LEADTIME)

我也尝试过:

insert into manufactured values (101,1,'Warehouse1');

我得到了错误:

ORA-00947:值不足

最后是这样:

insert into manufactured(PID, PARTTYPE, LEAD_TIME) VALUES (102, 2, '2 WEEKS');

我收到以下错误: ORA-02290:违反了检查约束(****。LEADTIME2)

预先感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

此插入语句:

  

插入制成品(PID,PARTTYPE,LOCATION)   values(101,1,'Warehouse1');

...失败,因为您的LEADTIME约束要求PARTTYPE=2。 (这是一个AND条件,因此如果PARTTYPE=1约束将失败,而与LEAD_TIME的值无关)。

这是我认为您要寻找的:

CREATE TABLE manufactured (
PID INT NOT NULL,
PARTTYPE NUMBER (1) NOT NULL,
CHECK (PARTTYPE IN (1,2)),
CONSTRAINT REFMAN FOREIGN KEY (PID, PARTTYPE) REFERENCES PART (PID, PARTTYPE),
LOCATION VARCHAR (50),
--CONSTRAINT LOC CHECK (PARTTYPE=1 AND LOCATION IS NOT NULL),
--CONSTRAINT LOC2 CHECK(PARTTYPE=2 AND LOCATION IS NULL),
CONSTRAINT LOC CHECK (PARTTYPE=1 AND LOCATION IS NOT NULL OR PARTTYPE=2 AND LOCATION IS NULL),
LEAD_TIME VARCHAR (50),
--CONSTRAINT LEADTIME CHECK (PARTTYPE=2 AND LEAD_TIME IS NOT NULL),
--CONSTRAINT LEADTIME2 CHECK (PARTTYPE=1 AND LEAD_TIME IS NULL),
CONSTRAINT LEADTIME CHECK (PARTTYPE=1 AND LEAD_TIME IS NULL OR PARTTYPE=2 AND LEAD_TIME IS NOT NULL),
CONSTRAINT PK_MAN PRIMARY KEY (PID));

基本上,对每列设置一个约束,以强制执行该列的整个逻辑集。

如果您确实希望每列有两个约束,您也可以这样做。如果是这样,请发表评论,我将更新此答案。否则,我不想使问题混乱/混乱。

答案 1 :(得分:0)

我不知道您使用哪个RDBMS。例如,在Oracle CHECK约束中接受空值。

我看到每种参与方类型都有不同的属性/数据类型。有两种方法:

  1. 将数据拆分为两个单独的表。在此解决方案中,可能需要一些触发器。
    • tab1:捏造_1(PID 1的属性+约束)
    • tab2:制造商_2(PID 2的属性+约束)
  2. 使用“插入/更新后”触发器-它将不必要的数据设置为null。例如,如果表中的时间是PID = 1的时间,则触发器将时间值设置为null。

答案 2 :(得分:0)

  • 针对

    的错误ORA-00947: not enough values

    insert into manufactured values (101,1,'Warehouse1');很明显

    因为lead_time列表中缺少表(manufactured)的最后一列(values)。

  • 错误ORA-02290: check constraint源于从属 检查约束LEADTIMELEADTIME2中的条件, 这些应该合并为
    CONSTRAINT LEADTIME CHECK ((PARTTYPE=2 AND LEAD_TIME IS NOT NULL) OR (PARTTYPE=1 AND LEAD_TIME IS NULL))

  • 对于约束LOCLOC2应该产生的约束,同样的逻辑也起作用

    CONSTRAINT LOC CHECK ((PARTTYPE=1 AND LOCATION IS NOT NULL) OR (PARTTYPE=2 AND LOCATION IS NULL))