问题
i'v been learning SQL for the last week but I am unsure how to correctly add a case statement within a check constraint. Can anybody give me any pointers?
I have the following grade 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'))
);
I want to check that if the salary_grade
is between A-D then the salary_scale
must be 'S1' or if the salary_grade
is between E-G then it's 'S2'.
I have tried to research this and come up with the latter but however it does not work.. have I structured the code correctly?
回答1:
I think you can do the following:
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.
You don't need the UPPER()
constraint on salary_grade
since the regex check will suffice (you're already checking to make sure it's an uppercase letter between A and G). I don't think the constraint on salary_scale
alone is necessary either since it would be contained, logically, in the last constraint.
UPDATE
Here is how you might do it with a CASE
statement:
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.
回答2:
A case
has to be compared to something, which is why you are getting the missing right parenthesis error. Unless you particularly want a case
, you can just check the combination with 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')),
SQL Fiddle demo.
As Parado has said, you can't use constraints to set column values conditionally, only to restrict them. You could potentially use a virtual column for the scale, but it would mean putting part of a look-up table into the DDL rather than the data, which seems a bit strange.
回答3:
Check Constraints
is used to test data before insert to protect data structure from fake data. Actually we use case
in select
statement. You can't use it for conditional insert. If you want to change data for particular column before insert you need to use trigger
or you can also use virtual column
but which has some restrictions.
More information you can find here
- check constraints
- triggers
- virtual columns
来源:https://stackoverflow.com/questions/28158144/using-a-case-statement-in-a-check-constraint