Rud*_*lan 6 postgresql trigger database-design constraint check-constraints
我有一个 PostgreSQL 表phase_steps
,包含以下示例行:
phase_step_id|step_type|step_status|
-------------+---------+-----------+
1| RESEARCH| |
2| SURVEY| |
Run Code Online (Sandbox Code Playgroud)
更新step_status
列的值取决于该值
step_type
是什么。
当step_type
为“RESEARCH”时,只能输入“COMPLETE”或“INCOMPLETE”值step_status
。
当step_type
为“SURVEY”时,只能输入“ASSIGNED”或“NOT ASSIGNED”值step_status
。
step_status
我尝试通过以下过程管理“研究”约束:
create or replace function insert_step_status_value() returns trigger as $$
begin
if (new.step_status != 'COMPLETE') or (new.step_status != 'INCOMPLETE')
from phase_steps where step_type = 'RESEARCH'
then
raise exception 'Status value not in range for this phase step';
end if;
return new;
end;
$$ language plpgsql;
create trigger check_step_status_value before update on phase_steps
for each row execute procedure insert_step_status_value();
Run Code Online (Sandbox Code Playgroud)
然而,像这样的插入
update jobs.phase_steps
set step_status_lu = 'INCOMPLETE'
where phase_step_id = 1;
Run Code Online (Sandbox Code Playgroud)
给出错误:
Run Code Online (Sandbox Code Playgroud)SQL Error [P0001]: ERROR: Status value not in range for this phase step Where: PL/pgSQL function insert_step_status_value() line 6 at RAISE
想法?
约束CHECK
就可以完成这项工作。比触发器更简单、更便宜、更可靠。
要强制执行列出的组合,您的表定义可能如下所示:
CREATE TABLE jobs.phase_steps (
phase_step_id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY
, step_type text
, step_status text
, CONSTRAINT step_status_for_step_type CHECK (
step_type = 'RESEARCH' AND step_status IN ('COMPLETE', 'INCOMPLETE')
OR step_type = 'SURVEY' AND step_status IN ('ASSIGNED', 'NOT ASSIGNED')
)
);
Run Code Online (Sandbox Code Playgroud)
或者更简单的等价形式:
, CONSTRAINT step_status_for_step_type CHECK (
(step_type, step_status)
IN (('RESEARCH', 'COMPLETE')
, ('RESEARCH', 'INCOMPLETE')
, ('SURVEY' , 'ASSIGNED')
, ('SURVEY' , 'NOT ASSIGNED')))
Run Code Online (Sandbox Code Playgroud)
定义约束有两种方式:表约束和列约束。列约束被定义为列定义的一部分。表约束定义不依赖于特定列,并且它可以包含多个列。
运算符优先级对我们有利,不需要额外的括号。
不允许(step_type, step_status)
-除了null
value之外的任何其他组合值。CHECK
如果表达式的计算结果为true
or ,则传递约束null
。
在这种情况下,您可能想要向 添加NOT NULL
约束step_type
,那么step_status
仍然可以是null
,并且step_type
可以是任何内容(但是)。null
但如果step_status
有值,则组合必须通过检查。
或者,也不允许 的任何其他值step_type
:
ALTER TABLE phase_steps
DROP CONSTRAINT step_status_for_step_type
, ADD CONSTRAINT step_status_for_step_type CHECK (
CASE step_type WHEN 'RESEARCH' THEN step_status IN ('COMPLETE', 'INCOMPLETE')
WHEN 'SURVEY' THEN step_status IN ('ASSIGNED', 'NOT ASSIGNED')
ELSE false END);
Run Code Online (Sandbox Code Playgroud)
现在step_type
(包括null
)的任何其他值都会到达ELSE
分支并进行检查false
。(但null
仍然step_status
过去了。)
归档时间: |
|
查看次数: |
7905 次 |
最近记录: |