关系数据库检查约束ORACLE

Relational Databases Check Constraint ORACLE

我正在为 Uni 做一个项目,我对数据库没有太多的了解或经验。我正在尝试在 Oracle 中使用 table 创建一个数据库,其中包含可以是 2 种类型的制造零件,比如 1 和 2。当零件是类型 1 时,我将在 table 中存储它位置,当它是类型 2 时,我将在相同的 table 中存储提前期。因此,在这两种情况下,另一列都会有空值(我知道空值的问题,但在考虑并研究了处理这个问题的最佳方法之后,我决定这样做,因为我只有少量属性)。我的问题出在 CHECK CONSTRAINT 中。我试过这样做:

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)

预先感谢您的帮助。

我不知道你用的是哪个RDBMS。例如在 Oracle CHECK 约束中接受空值。

据我所知,每种派对类型都有不同的 attributes/datatypes。有两种方法:

  1. 将数据分成两个单独的 table。在此解决方案中,可能需要一些触发器。
    • tab1:manufactured_1(PID 1 的属性+约束)
    • tab2:manufactured_2(PID 2 的属性+约束)
  2. 使用 "after insert/update" 触发器 - 它会将不必要的数据设置为空。例如,如果在 table 中 PID = 1 的时间比触发器会将时间值设置为空。

这条插入语句:

insert into manufactured(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));

基本上,对每一列进行一个约束,强制执行该列的整套逻辑。

如果您真的想要在每一列上设置两个约束,您也可以这样做。如果是这样,post 发表评论,我将更新此答案。否则我不想 clutter/confuse 这个问题。

  • 的错误 ORA-00947: not enough values

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

    因为 table(manufactured) 的最后一列 (lead_time) 对于 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))