在检查约束中使用 case 语句
Using a case statement in a check constraint
上周我一直在学习 SQL,但我不确定如何在检查约束内正确添加 case 语句。任何人都可以给我任何指示吗?
我的成绩如下table:
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
在 A-D 之间那么 salary_scale
必须是 'S1' 或者如果 salary_grade
在 E-G 之间那么它是 'S2'.
我曾尝试对此进行研究并提出后者,但是它不起作用..我是否正确构建了代码?
A case
必须与某物进行比较,这就是为什么您会收到缺少右括号错误的原因。除非你特别想要 case
,否则你可以用 and/or:
检查组合
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')),
正如 Parado 所说,您不能使用约束来有条件地设置列值,只能限制它们。您可能会使用虚拟列作为比例尺,但这意味着将查找的一部分 table 放入 DDL 而不是数据,这看起来有点奇怪。
Check Constraints
用于在插入前测试数据,以保护数据结构免受假数据的影响。实际上我们在 select
语句中使用 case
。 您不能将其用于条件插入。如果你想在插入之前更改特定列的数据,你需要使用 trigger
或者你也可以使用 virtual column
但有一些限制。
您可以在此处找到更多信息
我认为你可以做到以下几点:
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.
您不需要 salary_grade
上的 UPPER()
约束,因为正则表达式检查就足够了(您已经在检查以确保它是 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 )
);
上周我一直在学习 SQL,但我不确定如何在检查约束内正确添加 case 语句。任何人都可以给我任何指示吗?
我的成绩如下table:
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
在 A-D 之间那么 salary_scale
必须是 'S1' 或者如果 salary_grade
在 E-G 之间那么它是 'S2'.
我曾尝试对此进行研究并提出后者,但是它不起作用..我是否正确构建了代码?
A case
必须与某物进行比较,这就是为什么您会收到缺少右括号错误的原因。除非你特别想要 case
,否则你可以用 and/or:
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')),
正如 Parado 所说,您不能使用约束来有条件地设置列值,只能限制它们。您可能会使用虚拟列作为比例尺,但这意味着将查找的一部分 table 放入 DDL 而不是数据,这看起来有点奇怪。
Check Constraints
用于在插入前测试数据,以保护数据结构免受假数据的影响。实际上我们在 select
语句中使用 case
。 您不能将其用于条件插入。如果你想在插入之前更改特定列的数据,你需要使用 trigger
或者你也可以使用 virtual column
但有一些限制。
您可以在此处找到更多信息
我认为你可以做到以下几点:
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.
您不需要 salary_grade
上的 UPPER()
约束,因为正则表达式检查就足够了(您已经在检查以确保它是 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 )
);