在检查约束中使用case语句

时间:2015-01-26 20:26:36

标签: sql oracle oracle11g check-constraints

我上周一直在学习SQL,但我不确定如何在检查约束中正确添加case语句。任何人都可以给我任何指示吗?

我有以下成绩表:

CREATE TABLE Grade
(
    salary_grade    char(1) NOT NULL CHECK (salary_grade = UPPER(salary_grade)),
        CONSTRAINT ck_grade_scale CHECK(
        CASE 
            WHEN salary_grade = '[A-D]' 
                THEN salary_scale = 'S1'
            WHEN salary_grade = '[D-G]' 
                THEN salary_scale = 'S2'
        END)

        salary_scale    char(2) DEFAULT 'S1' NOT NULL,

        CONSTRAINT pk_grade PRIMARY KEY (salary_grade),
        CONSTRAINT ck_salary_grade CHECK (REGEXP_LIKE(salary_grade, '[A-G]', 'c')),
        --constraint must be either S1 or S2
        CONSTRAINT ck_salary_scale CHECK (salary_scale IN ('S1', 'S2'))
);

我想检查一下,如果salary_grade介于AD之间,那么salary_scale必须是'S1',或者salary_grade介于EG之间,那么它就是'S2'。

我试图对此进行研究并提出后者但是它不起作用..我是否正确构建了代码?

3 个答案:

答案 0 :(得分:6)

我认为你可以做到以下几点:

CREATE TABLE Grade
(
  salary_grade    char(1) NOT NULL CHECK (REGEXP_LIKE(salary_grade, '[A-G]', 'c')),
  salary_scale    char(2) DEFAULT 'S1' NOT NULL,
  CONSTRAINT pk_grade PRIMARY KEY (salary_grade),
  CONSTRAINT ck_grade_scale CHECK ( REGEXP_LIKE(salary_grade, '[A-D]', 'c') AND salary_scale = 'S1'
                                 OR REGEXP_LIKE(salary_grade, '[E-G]', 'c') AND salary_scale = 'S2' )
);

Please see SQL Fiddle schema here.

UPPER()上不需要salary_grade约束,因为正则表达式检查就足够了(您已经检查过以确保它是A和G之间的大写字母)。我不认为单独对salary_scale的约束是必要的,因为它在逻辑上包含在最后一个约束中。

<强>更新

以下是使用CASE语句执行此操作的方法:

CREATE TABLE Grade
(
  salary_grade    char(1) NOT NULL CHECK (REGEXP_LIKE(salary_grade, '[A-G]', 'c')),
  salary_scale    char(2) DEFAULT 'S1' NOT NULL,  
  CONSTRAINT pk_grade PRIMARY KEY (salary_grade),
  CONSTRAINT ck_grade_scale CHECK ( salary_scale = CASE WHEN REGEXP_LIKE(salary_grade, '[A-D]', 'c') THEN 'S1' ELSE 'S2' END )
);

Please see SQL Fiddle schema here.

答案 1 :(得分:4)

必须将case与某些东西进行比较,这就是为什么你会得到缺少的右括号错误。除非您特别想要case,否则您只需检查组合和/或:

CONSTRAINT ck_grade_scale CHECK(
    (salary_grade BETWEEN 'A' AND 'D' AND salary_scale = 'S1')
    OR (salary_grade BETWEEN 'D' AND 'G' AND salary_scale = 'S2')),

SQL Fiddle demo

正如Parado所说,你不能使用约束来有条件地设置列值,只是为了限制它们。您可能会使用虚拟列作为比例,但这意味着将查找表的一部分放入DDL而不是数据,这看起来有点奇怪。

答案 2 :(得分:2)

Check Constraints用于在插入之前测试数据,以保护数据结构免受虚假数据的影响。实际上我们在case语句中使用select您无法将其用于条件插入。如果要在插入之前更改特定列的数据,则需要使用trigger,或者也可以使用virtual column但有一些限制。

您可以在此处找到更多信息