是否可以在 DB2 z/OS 的检查约束中执行 SQL 函数
Should it be possible to execute an SQL function in a check constraint within DB2 z/OS
DDL 的简单版本:
create function rm00dv1.no_concurrent_schedules()
returns integer
LANGUAGE SQL
READS SQL DATA
NO EXTERNAL ACTION
NOT DETERMINISTIC
BEGIN
declare num_overlaps integer;
select count(*)
into num_overlaps
from
rm00dv1.schedules a
where
a.id != 0
and
exists (
select 1
from rm00dv1.schedules b
where
b.id = 0 -- matches the key of a given record
and rm00dv1.isConcurrent(b.schdl_eff_dt, b.schdl_trm_dt, a.schdl_eff_dt, a.schdl_trm_dt) != 0
);
return num_overlaps;
end;
Table:
create table rm00dv1.schedules (
id int not null,
schdl_eff_dt date not null,
schdl_trm_dt date not null,
info_chg_ts timestamp(6) not null with default
)
in RM00DV1.TSRMDV01 ;
alter table rm00dv1.schedules add constraint no_schedule_overlap
check ((schdl_trm_dt < '01/01/2015')
or
rm00dv1.no_concurrent_schedules() <= 0);
我得到一个 SQL00551N - no execution privilege
,这很奇怪,因为我可以在 select 语句中执行函数。
有解决这个问题的办法吗?
谢谢。
看来你做不到。我正在查看 the DB2 10 for z/OS reference for ALTER TABLE 参考资料,它在 CHECK(检查条件) 下显示以下内容:"A check-condition is a search condition, with the following restrictions: ... must not contain... Built-in or user-defined functions...".
由于您的函数看起来不会转换为检查条件,因此在 table 上定义触发器可能是下一个最佳选择。
我了解到 AFTER 触发器不会像 BEFORE 触发器那样得到 -746。我真的很想使用 CONSTRAINT,因为它最能捕捉到我之后的人的意图,并使用 BEFORE 触发器来终止活动计划。但是,看起来一系列触发器将成为解决之道。这有点笨拙,因为所有触发器都必须单独创建,您必须一起查看它们才能获得意图,而且正确的行为取决于它们的创建顺序。是的,记录在案,它们将按照创建的顺序执行。
没有指定终止日期的行的快乐路径终止:
CREATE TRIGGER terminate_no_trm
after
INSERT ON schedules
referencing new as new
FOR EACH ROW
MODE DB2SQL
BEGIN ATOMIC
update schedules
set
schdl_trm_dt = max(schdl_eff_dt, new.schdl_eff_dt - 1 days) -- prob not necessary, but don't set the trm before the eff
, info_chg_ts = new.info_chg_ts
where
new.keyCombo = keyCombo
and
schdl_trm_dt = '9999-12-31'
and schdl_eff_dt < new.schdl_eff_dt;
end
如果插入导致重叠,则阻止插入行:
CREATE TRIGGER no_overlapping_schedules_i
after
insert ON schedules
referencing new as n
FOR EACH ROW
MODE DB2SQL
when (num_concurrent_schedules(n.keyCombo) > 0)
begin atomic
SIGNAL SQLSTATE '75001' (
'Concurrent schedules detected: '
concat ' ' concat cast(n.keyCombo as varchar(32))
concat ': ' concat cast(n.schdl_eff_dt as varchar(32))
concat ' to ' concat cast(n.schdl_trm_dt as varchar(32))
);
end
如果更新会导致重叠,则阻止更新
CREATE TRIGGER no_overlapping_schedules_u
after
update ON schedules
referencing new as n
FOR EACH ROW
MODE DB2SQL
when (num_concurrent_schedules(n.keyCombo) > 0)
begin atomic
SIGNAL SQLSTATE '75001' (
'Concurrent schedules detected: '
concat ' ' concat cast(n.keyCombo as varchar(32))
concat ': ' concat cast(n.schdl_eff_dt as varchar(32))
concat ' to ' concat cast(n.schdl_trm_dt as varchar(32))
);
end
谢谢你的想法。
DDL 的简单版本:
create function rm00dv1.no_concurrent_schedules()
returns integer
LANGUAGE SQL
READS SQL DATA
NO EXTERNAL ACTION
NOT DETERMINISTIC
BEGIN
declare num_overlaps integer;
select count(*)
into num_overlaps
from
rm00dv1.schedules a
where
a.id != 0
and
exists (
select 1
from rm00dv1.schedules b
where
b.id = 0 -- matches the key of a given record
and rm00dv1.isConcurrent(b.schdl_eff_dt, b.schdl_trm_dt, a.schdl_eff_dt, a.schdl_trm_dt) != 0
);
return num_overlaps;
end;
Table:
create table rm00dv1.schedules (
id int not null,
schdl_eff_dt date not null,
schdl_trm_dt date not null,
info_chg_ts timestamp(6) not null with default
)
in RM00DV1.TSRMDV01 ;
alter table rm00dv1.schedules add constraint no_schedule_overlap
check ((schdl_trm_dt < '01/01/2015')
or
rm00dv1.no_concurrent_schedules() <= 0);
我得到一个 SQL00551N - no execution privilege
,这很奇怪,因为我可以在 select 语句中执行函数。
有解决这个问题的办法吗? 谢谢。
看来你做不到。我正在查看 the DB2 10 for z/OS reference for ALTER TABLE 参考资料,它在 CHECK(检查条件) 下显示以下内容:"A check-condition is a search condition, with the following restrictions: ... must not contain... Built-in or user-defined functions...".
由于您的函数看起来不会转换为检查条件,因此在 table 上定义触发器可能是下一个最佳选择。
我了解到 AFTER 触发器不会像 BEFORE 触发器那样得到 -746。我真的很想使用 CONSTRAINT,因为它最能捕捉到我之后的人的意图,并使用 BEFORE 触发器来终止活动计划。但是,看起来一系列触发器将成为解决之道。这有点笨拙,因为所有触发器都必须单独创建,您必须一起查看它们才能获得意图,而且正确的行为取决于它们的创建顺序。是的,记录在案,它们将按照创建的顺序执行。
没有指定终止日期的行的快乐路径终止:
CREATE TRIGGER terminate_no_trm
after
INSERT ON schedules
referencing new as new
FOR EACH ROW
MODE DB2SQL
BEGIN ATOMIC
update schedules
set
schdl_trm_dt = max(schdl_eff_dt, new.schdl_eff_dt - 1 days) -- prob not necessary, but don't set the trm before the eff
, info_chg_ts = new.info_chg_ts
where
new.keyCombo = keyCombo
and
schdl_trm_dt = '9999-12-31'
and schdl_eff_dt < new.schdl_eff_dt;
end
如果插入导致重叠,则阻止插入行:
CREATE TRIGGER no_overlapping_schedules_i
after
insert ON schedules
referencing new as n
FOR EACH ROW
MODE DB2SQL
when (num_concurrent_schedules(n.keyCombo) > 0)
begin atomic
SIGNAL SQLSTATE '75001' (
'Concurrent schedules detected: '
concat ' ' concat cast(n.keyCombo as varchar(32))
concat ': ' concat cast(n.schdl_eff_dt as varchar(32))
concat ' to ' concat cast(n.schdl_trm_dt as varchar(32))
);
end
如果更新会导致重叠,则阻止更新
CREATE TRIGGER no_overlapping_schedules_u
after
update ON schedules
referencing new as n
FOR EACH ROW
MODE DB2SQL
when (num_concurrent_schedules(n.keyCombo) > 0)
begin atomic
SIGNAL SQLSTATE '75001' (
'Concurrent schedules detected: '
concat ' ' concat cast(n.keyCombo as varchar(32))
concat ': ' concat cast(n.schdl_eff_dt as varchar(32))
concat ' to ' concat cast(n.schdl_trm_dt as varchar(32))
);
end
谢谢你的想法。