1

我有一张“学生”表和几个属性——其中两个在这个特定问题中很重要。我需要确保任何具有“初级”分类(年级)的学生的时间正好在 55 到 84 小时之间(学分)。

这是我迄今为止在 Oracle 中的声明方式(删除了不必要的代码):

CREATE TABLE Students (  
id INTEGER,  
name CHAR(10) NOT NULL,  
classification CHAR(10) NOT NULL,  
hours INTEGER,  
gpa NUMBER(3,2) NOT NULL,  
mentor INTEGER,  
-- IC4:  
-- To be classified as a 'junior', a student must have  
-- completed between 55 and 84 hours (inclusive).  
CONSTRAINT IC4 CHECK (classification != 'junior' AND (hours < 55 AND hours > 84))),  
);

甲骨文抛出错误:

第 23 行的错误:  
ORA-00922: 缺少或无效选项  

我确定我没有正确格式化约束,但是我的教授花了大约 3 秒钟的时间来声明并告诉我们自己弄清楚。我知道 1 属性约束,但我不知道如何同时混合和匹配 2 个属性。有人可以帮我吗?

*基本上在任何其他代码中,它看起来像嵌套的 if 语句:

if (classification == "junior") {  
    if (hours < 55 && hours > 84)  
        throwSomeError("Foolish!");  
}

我似乎无法将其转换为 SQL。如果这该死的东西中的间距很奇怪,我很抱歉,我无法将其格式化以挽救我的生命。

4

4 回答 4

1

末尾有一个逗号,还有一个太多的右括号:

...84))),);

除非您在发布之前删除了某些内容,否则可能是错误引用第 23 行的情况(但希望不会因为在您根本看不到的代码中看到问题很棘手)。如果变成:

...84)));

但正如其他人所指出的那样,无论如何情况都是错误的。获得我认为您想要的结果的一种方法是:

...
CONSTRAINT IC4 CHECK (classification != 'junior' OR hours BETWEEN 55 AND 84)
);

OR表示仅当为hours时才应用检查,其他不受限制。(如果您需要针对不同分类的不同规则,请查看评论中链接到的非常相似的问题Chris Saxon)。classification'junior'classification

有一些测试数据:

insert into students values (1, 'A', 'junior', 54, 1, 1); -- ORA-02290
insert into students values (2, 'B', 'junior', 55, 1, 1); -- OK
insert into students values (3, 'C', 'junior', 84, 1, 1); -- OK
insert into students values (4, 'D', 'junior', 85, 1, 1); -- ORA-02290

insert into students values (5, 'E', 'senior', 54, 1, 1); -- OK
insert into students values (6, 'F', 'senior', 55, 1, 1); -- OK
insert into students values (7, 'G', 'senior', 84, 1, 1); -- OK
insert into students values (8, 'H', 'senior', 85, 1, 1); -- OK

select * from students order by id;

  ID NAME       CLASSIFICATION HOURS GPA MENTOR
---- ---------- -------------- ----- --- ------
   2 B          junior            55  1.00      1 
   3 C          junior            84  1.00      1 
   5 E          senior            54  1.00      1 
   6 F          senior            55  1.00      1 
   7 G          senior            84  1.00      1 
   8 H          senior            85  1.00      1 

 6 rows selected 

BETWEEN是包容性的,所以这与:

CONSTRAINT IC4 CHECK (classification != 'junior' OR (hours >= 55 AND hours <= 84))

您可能还需要一个检查约束classification,特别是因为这个约束是区分大小写的;或者最好有一个单独的classification表,并且对该表中的列有一个外键约束。但这可能超出了您对该作业的控制范围。

于 2013-02-04T07:39:59.413 回答
0

难道hours是允许Null的并且CHECK不能处理允许Nulls的字段吗?

因此,如果您认为,请尝试制作hours integer Not NULL并给出默认值..

另外你的情况不匹配..也检查一下....

于 2013-02-04T05:52:53.393 回答
0

如果您想检查“初级”的值是否应在 55 到 84 之间,请使用以下可编译代码 -

CREATE TABLE Students 
( id INTEGER, 
name CHAR(10) NOT NULL,
 classification CHAR(10) NOT NULL,
 hours INTEGER, gpa NUMBER(3,2) NOT NULL,
 mentor INTEGER, -- IC4: 
-- To be classified as a 'junior', 
a student must have -- completed between 55 and 84 hours (inclusive). 
CONSTRAINT IC4 CHECK (classification = 'junior' AND (hours >= 55 AND hours <= 84))) ;
于 2013-02-04T07:16:31.140 回答
0

似乎您的约束中的逻辑可能已关闭。小时不能小于 55 和大于 84。尝试使用 OR:

CONSTRAINT IC4 CHECK (classification != 'junior' AND (hours < 55 OR hours > 84))

但是,这并不能确保当分类 = 'junior' 时,小时数在 55 到 84 之间。尝试改用它:

CONSTRAINT IC4 CHECK (classification = 'junior' AND hours >= 55 AND hours <= 84))

祝你好运。

于 2013-02-04T06:04:32.423 回答