约束,如何将属性的值与另一个值进行比较?

时间:2012-10-17 03:22:09

标签: sql ddl

这是一个非常初学的问题,但我的谷歌技能让我失望,我似乎无法在笔记中找到任何内容。

在我的任务中,我必须根据教授给出的标准创建几个约束。

我们有一个名为Employee的表。员工有一个等级(char),该等级可以是'DB Guru','DB expert'或'DB newokie'。他们也有工资(整数)。这种约束我很容易做到。

之后的约束是确保排名为“DB guru”的人的薪水高于200.

我很困惑,我如何检查等级的值是否为'DB guru',并检查工资是否高于200.这是检查我看不到的排名的代码找到该怎么做。

这是我到目前为止所尝试的:

IC2: The salary of a 'DB guru' is above 200. 
*/ 
CONSTRAINT IC2 CHECK(rank IN('DB guru') AND  salary > 200)),

这给了我错误: 第14行的错误: ORA-00922:缺少或无效选项

第14行是我发布的Cconstraint,所以我猜这是一个语法错误。

有人能告诉我一个比较这些值的正确语法示例吗?

提前感谢您的帮助。

编辑:这是整个Create语句,以及我对每个约束的尝试。

-- IMPORTANT: use the names IC1, IC2, etc. as given below. 
-- -------------------------------------------------------------------- 
DROP TABLE Employee CASCADE CONSTRAINTS; 
DROP TABLE Dependent CASCADE CONSTRAINTS; 
-- 
CREATE TABLE Employee 
( 
id      INTEGER PRIMARY KEY, 
name    CHAR(10)  NOT NULL,  
rank    CHAR(10) NOT NULL, 
salary  INTEGER NOT NULL, 
/* 
IC1: The rank is one of: 'DB guru', 'DB expert', or 'DB rookie' 
*/ 
COnstraing IC1 CHECK(rank IN('DB guru', 'DB expert', 'DB rookie')),

IC2: The salary of a 'DB guru' is above 200. 
*/ 
CONSTRAINT IC2 CHECK(rank IN('DB guru') AND salary > 200)),
/* 
IC3: The salary of a 'DB expert' is between 80 and 220 (inclusive). 
*/ 
CONSTRAINT IC3 CHECK(rank IN('DB expert) AND salary >= 80 AND salary <= 220),
/* 
IC4: The salary of a 'DB rookie' is less than 100. 
*/ 
CONSTRAINT IC4 CHECK(rank IN('DB rookie') AND salary < 100))
); 

2 个答案:

答案 0 :(得分:2)

再次考虑一下这张支票的内容:

CONSTRAINT IC2 CHECK(rank IN('DB guru') AND salary > 200))

这就是说,对于每个行,rank必须完全等于'DB Guru',而salary必须大于200.这是你想要什么。你需要反过来思考 - 如果rank其他而不是'DB Guru',那么你不关心(在这个约束条件下)他们的薪水是多少。所以你真的想要:

CONSTRAINT IC2 CHECK(rank != 'DB guru' OR salary > 200)

最后你还有一个额外的)(在第一个例子中计算(),你会发现它们没有平衡)。您在IC4的末尾有类似的错误。


@wildplasser的补充工具栏 - 正如我所说,我们的两个IC2是等价的,使用了一点布尔逻辑:

NOT( zrank IN('DB guru') AND salary <= 200) --Your IC2

等于:

(NOT zrank IN ('DB guru')) OR (NOT salary <= 200) --De Morgan's law

等于:

(zrank != 'DB guru') OR (NOT salary <= 200) --Simplification of first

等于:

(zrank != 'DB guru') OR (salary > 200) --Simplification of second

等于:

zrank != 'DB guru' OR salary > 200 --Removal of brackets, my IC2

答案 1 :(得分:1)

-- -------------------------------------------------------------------- 
-- IMPORTANT: use the names IC1, IC2, etc. as given below. 
-- -------------------------------------------------------------------- 

DROP TABLE Employee CASCADE ;
-- 
CREATE DOMAIN dbarank AS CHAR(10) CHECK (VALUE IN ('DB guru', 'DB expert', 'DB rookie') );

CREATE TABLE Employee
( id      INTEGER PRIMARY KEY
, name    CHAR(10)  NOT NULL
, zrank    dbarank NOT NULL -- "rank" is a reserved name
, salary  INTEGER NOT NULL

-- IC2: The salary of a 'DB guru' is above 200. 
, CONSTRAINT IC2 CHECK ( NOT( zrank IN('DB guru') AND salary <= 200))

-- IC3: The salary of a 'DB expert' is between 80 and 220 (inclusive). 
, CONSTRAINT IC3 CHECK ( NOT (zrank IN ('DB expert') AND ( salary < 80 OR salary > 220)))
-- IC4: The salary of a 'DB rookie' is less than 100. 
, CONSTRAINT IC4 CHECK ( NOT (zrank IN('DB rookie') AND salary >= 100))
);
INSERT INTO Employee(id,name,zrank,salary) VALUES(1, 'Pipo', 'Clown', 1);
INSERT INTO Employee(id,name,zrank,salary) VALUES(1, 'Lutser', 'DB rookie', 110);
INSERT INTO Employee(id,name,zrank,salary) VALUES(1, 'Prutser', 'DB rookie', 90);

注意:由于我使用了Postgres,因此语法略有不同。 Oracle确实有域,因此将IC1实现为域约束的“技巧”仍然有效。

结果:

CREATE DOMAIN
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "employee_pkey" for table "employee"
CREATE TABLE
ERROR:  value for domain dbarank violates check constraint "dbarank_check"
ERROR:  new row for relation "employee" violates check constraint "ic4"
INSERT 0 1

更新:修复NOT(AND / OR)内容,使约束成为独占。