2016-12-05 1 views
0

version simple du DDL:Faut-il possible d'exécuter une fonction SQL dans une contrainte de vérification au sein de DB2 z/OS

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; 

Tableau:

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); 

Je reçois un SQL00551N - no execution privilege et que est étrange car je peux exécuter la fonction dans une instruction select.

Une idée pour résoudre ce problème? Merci.

Répondre

1

On dirait que vous ne pouvez pas. Je regarde the DB2 10 for z/OS reference for ALTER TABLE référence et il est écrit ce qui suit sous CHECK (vérifier-condition): "A vérifier-condition est une condition de recherche, avec les restrictions suivantes: ... ne doit pas contenir ... Construit- dans ou fonctions définies par l'utilisateur ... ".

Étant donné que votre fonction semble ne pas être convertie en condition de vérification, la définition de déclencheurs sur la table peut être la meilleure option suivante.

+1

Darn. J'ai relu ce document, mais j'ai manqué cette balle. Merci. FYI, quand je stub-dans une fonction intégrée, min (1,0), je reçois un message d'erreur qui a du sens, la contrainte de vérification est invalide. Donc, indépendamment des privilèges sur WLM, cette approche ne va pas fonctionner. –

+0

FYI, un déclencheur en lui-même ne fonctionnera pas non plus car la validité de l'opération d'insertion ou de mise à jour dépend des valeurs déjà présentes dans la table et vous ne pouvez pas accéder à la table. Je me suis heurté à cela, http://www.ibm.com/support/knowledgecenter/SSEPEK_11.0.0/codes/src/tpc/n746.html –

+0

@ChrisGolledge Puis-je vous demander comment vous avez fini par résoudre le problème? – David

0

J'ai appris que les déclencheurs AFTER n'obtiennent pas un -746 comme le font les déclencheurs BEFORE. J'avais vraiment voulu utiliser une CONTRAINTES parce que cela capture mieux l'intention pour les personnes qui viennent après moi, avec un déclencheur BEFORE pour mettre fin aux horaires actifs. Mais, il semble qu'une séquence de déclencheurs va être la voie à suivre. C'est un peu maladroit car les déclencheurs doivent tous être créés séparément et vous devez les regarder ensemble pour obtenir l'intention, et parce que le comportement correct dépend de leur ordre de création. Oui, il est documenté qu'ils seront exécutés dans l'ordre de leur création.

terminaison de voie Heureux de lignes sans une date d'expiration spécifiée:

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 

Prevent insert de lignes si ce insert provoque un chevauchement:

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 

et empêcher mise à jour si cela donnerait lieu à un recouvrement

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 

Merci pour les idées.