I'm using a closure table to manage an organisation structure. The organisation 
table is defined as:
 CREATE TABLE ORGANISATION 
 (
   ORGID DOM_INTLARGE NOT NULL,
   ORG_NME DOM_VARCHARMEDIUM NOT NULL,
   LEVEL_NUM DOM_INTSMALL NOT NULL,
   INUSE DOM_BOOLN,
 CONSTRAINT PK_ORGANISATION PRIMARY KEY (ORGID),
 CONSTRAINT UN_ORGNME UNIQUE (ORG_NME, LEVEL_NUM)
 );
 

 and the closure table as:
 

 CREATE TABLE ORGCHART 
 (
   PARENTID DOM_INTLARGE NOT NULL,
   CHILDID DOM_INTLARGE NOT NULL,
   DEPTH DOM_INTSMALL NOT NULL,
 CONSTRAINT PK_ORGCHART PRIMARY KEY (PARENTID, CHILDID),
 CONSTRAINT FK_ORG2CHCHILD FOREIGN KEY (CHILDID) REFERENCES ORGANISATION 
(ORGID),
 CONSTRAINT ORG2CHPARENT FOREIGN KEY (PARENTID) REFERENCES ORGANISATION 
(ORGID));
 

 If I use the statements in the following stored procedure to move a part in 
the middle of the structure (where DEPTH =2 in the ORGCHART table) I get a 
PRIMARY or UNIQUE KEY constraint "PK_ORGCHART" constraint error as the delete 
statement hasn't removed all the required rows.
 

 SET TERM ^ ;
 CREATE PROCEDURE MOVEORGANISATION_OLD 
 (
   IN_ORGTOMOVE BIGINT,
   IN_WHERETOMOVE BIGINT
 )
 AS
 BEGIN 
 DELETE FROM orgchart
 WHERE childid IN (SELECT childid
 FROM OrgChart
 WHERE parentid = :IN_OrgToMove)
 AND parentid IN (SELECT parentid
 FROM OrgChart
 WHERE childid = :IN_OrgToMove
 AND parentid != childid);
 

 INSERT INTO OrgChart (ParentId, ChildId, depth)
 SELECT supertree.ParentId, subtree.ChildId, subtree.DEPTH + supertree.DEPTH + 1
 FROM OrgChart supertree
 CROSS JOIN OrgChart  subtree
 WHERE supertree.ChildId = :IN_WhereToMove
 AND subtree.ParentId = :IN_OrgToMove;
 

 END
  ^
 

 SET TERM ; ^
 

 

 However if I first store a list of the rows to be delete from ORGCHART table 
into a temporary table defined as:
 

 CREATE TABLE TMP_ORGCHANGE 
 (
   ORGID DOM_INTLARGE,
   PARENTID DOM_INTLARGE
 );
 

 and then use it in the where clause criteria of the delete statement 
everything works as expected (see revise procedure below).
  
 SET TERM ^ ;
 CREATE PROCEDURE MOVEORGANISATION 
 (
   IN_ORGTOMOVE BIGINT,
   IN_WHERETOMOVE BIGINT
 )
 AS
 BEGIN
 /*List records to be removed into temporary table */
 insert into TMP_ORGCHANGE (parentid, orgid)
 select parentid, childid FROM orgchart
 WHERE childid IN (SELECT childid
 FROM OrgChart
 WHERE parentid = :IN_OrgToMove)
 AND parentid IN (SELECT parentid
 FROM OrgChart
 WHERE childid = :IN_OrgToMove
 AND parentid != childid);
 

 /* now delete records  from ORGCHART */
 delete from ORGCHART
 where parentid in (select parentid from TMP_ORGCHANGE)
 and   childid in (select orgid from TMP_ORGCHANGE);
 

 /* create the new links */
 INSERT INTO OrgChart (ParentId, ChildId, depth)
 SELECT supertree.ParentId, subtree.ChildId, subtree.DEPTH + supertree.DEPTH + 1
 FROM OrgChart supertree
 CROSS JOIN OrgChart  subtree
 WHERE supertree.ChildId = :IN_WhereToMove
 AND subtree.ParentId = :IN_OrgToMove;
 END
  ^
 SET TERM ; ^
 

 
 Is there something that I'm doing wrong in the first procedure that prevents 
all relevant records from being deleted.
 

 Here is a sample dataset to illustrate. If I pass the values 5,2 to the first 
procedure the operation fails but passing them to the second procedure it 
succeeds. 
 

 
 INSERT INTO ORGANISATION (ORGID, ORG_NME, LEVEL_NUM, PARENTID, INUSE) VALUES 
('1', 'Whole Organisation', '0', NULL, NULL);
 INSERT INTO ORGANISATION (ORGID, ORG_NME, LEVEL_NUM, PARENTID, INUSE) VALUES 
('2', 'Div1', '1', '1', '1');
 INSERT INTO ORGANISATION (ORGID, ORG_NME, LEVEL_NUM, PARENTID, INUSE) VALUES 
('3', 'Div2', '1', '1', '1');
 INSERT INTO ORGANISATION (ORGID, ORG_NME, LEVEL_NUM, PARENTID, INUSE) VALUES 
('4', 'Dir11', '2', '2', '1');
 INSERT INTO ORGANISATION (ORGID, ORG_NME, LEVEL_NUM, PARENTID, INUSE) VALUES 
('5', 'Dir21', '2', '3', '1');
 INSERT INTO ORGANISATION (ORGID, ORG_NME, LEVEL_NUM, PARENTID, INUSE) VALUES 
('6', 'Spec111', '3', '4', '1');
 INSERT INTO ORGANISATION (ORGID, ORG_NME, LEVEL_NUM, PARENTID, INUSE) VALUES 
('7', 'Spec112', '3', '4', '1');
 INSERT INTO ORGANISATION (ORGID, ORG_NME, LEVEL_NUM, PARENTID, INUSE) VALUES 
('8', 'Spec211', '3', '5', '1');
 INSERT INTO ORGANISATION (ORGID, ORG_NME, LEVEL_NUM, PARENTID, INUSE) VALUES 
('9', 'Spec212', '3', '5', '1');
 

 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('1', '1', '0');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('2', '2', '0');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('1', '2', '1');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('3', '3', '0');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('1', '3', '1');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('4', '4', '0');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('2', '4', '1');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('1', '4', '2');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('5', '5', '0');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('3', '5', '1');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('1', '5', '2');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('6', '6', '0');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('4', '6', '1');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('2', '6', '2');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('1', '6', '3');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('7', '7', '0');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('4', '7', '1');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('2', '7', '2');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('1', '7', '3');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('8', '8', '0');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('5', '8', '1');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('3', '8', '2');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('1', '8', '3');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('9', '9', '0');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('5', '9', '1');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('3', '9', '2');
 INSERT INTO ORGCHART (PARENTID, CHILDID, DEPTH) VALUES ('1', '9', '3');
 


 

 

Reply via email to