Question

 CREATE TABLE SPONSORS (owner_number INT NOT NULL,       
                        requires_anonimity CHAR(3) NOT NULL,                                    
                        CONSTRAINT chk_requires_anonimity CHECK (requires_anonimity IN ('Yes', 'No')),      
                        FOREIGN KEY (owner_number) REFERENCES OWNER (owner_number),
                        PRIMARY KEY (owner_number));



CREATE TABLE DONATIONS (receipt_number NCHAR(6) CHECK(receipt_number BETWEEN 111111 AND 999999),
                        amount_donated NUMBER NOT NULL,
                        document_reference VARCHAR(50) UNIQUE ,
                        donations_event_number INT NOT NULL CHECK,
                        donations_sponsor_number INT NOT NULL,
                        FOREIGN KEY (donations_sponsor_number) REFERENCES SPONSORS(benefactor_number_sponspor) 
            );

What I am trying to get out of this command is the following instance, If Donator BOB decided to give £100 on conditions x and y which will be referenced in the document_reference, he should be able to put in place the same conditions for a future donation, but another individual cannot use his conditions

CREATE UNIQUE INDEX doc_unique_indx
ON DONATIONS ( CASE WHEN donations_sponsor_number = donations_sponsor_number THEN AllOW to use same document_reference ELSE END);
Was it helpful?

Solution 2

Dave Aldridg is 100% on the mark. This is why normalization is important - your problem is trivial if you have:

SPONSORS (OWNER_NUMBER PK, ...)

DOC_REFS (DOCUMENT_REFERENCE PK,
         DONOR_NUMBER FK REFERENCES SPONSORS(OWNER_NUMBER),
         ...)

DONATIONS (RECEIPT PK,
           DOCUMENT_REFERENCE FK REFERENCES DOC_REFS(DOCUMENT_REFERENCE),
           ...)

If at all possible, fix your model, split the table.

That said... if you had to do this the hard way, do NOT attempt to enforce constraints with triggers (unless only one person is allowed to use the database at a time). The only thing worse than no constraint at all is a false sense of security from a perceived constraint that isn't enforced. If you absolutely must solve this with the table at hand, you can pull off a deferred constraint using a "sanity-checking" FAST REFRESH MV:

CREATE TABLE SPONSORS (owner_number INT NOT NULL,       
                        requires_anonimity CHAR(3) NOT NULL,                                    
                        CONSTRAINT chk_requires_anonimity CHECK (requires_anonimity IN ('Yes', 'No')),      
                        PRIMARY KEY (owner_number));

CREATE TABLE DONATIONS (receipt_number NCHAR(6) CHECK(receipt_number BETWEEN 111111 AND 999999),
                        amount_donated NUMBER NOT NULL,
                        document_reference VARCHAR(50)  ,
                        donations_event_number INT NOT NULL ,
                        donations_sponsor_number INT NOT NULL,
                        FOREIGN KEY (donations_sponsor_number) REFERENCES SPONSORS(owner_number));

CREATE MATERIALIZED VIEW LOG ON DONATIONS WITH ROWID (DOCUMENT_REFERENCE, DONATIONS_SPONSOR_NUMBER) INCLUDING NEW VALUES

CREATE MATERIALIZED VIEW DOC_REF_CONSTRAINT 
REFRESH FAST ON COMMIT
AS 
SELECT DOCUMENT_REFERENCE, MIN(DONATIONS_SPONSOR_NUMBER) MX, MAX(DONATIONS_SPONSOR_NUMBER) MN
FROM DONATIONS
GROUP BY DOCUMENT_REFERENCE

CREATE INDEX DOC_REF_CONSTRAINT_IDX ON DOC_REF_CONSTRAINT(DECODE(MX,MN,0,1/0))


BEGIN
INSERT INTO SPONSORS VALUES (1, 'Yes');
INSERT INTO SPONSORS VALUES (2, 'Yes');
INSERT INTO DONATIONS VALUES ('111111',100,'A',0,1);
INSERT INTO DONATIONS VALUES ('222222',100,'A',0,1);
INSERT INTO DONATIONS VALUES ('333333',100,'C',0,2);
COMMIT;
END;
-- Success!

BEGIN
INSERT INTO SPONSORS VALUES (3, 'Yes');
INSERT INTO SPONSORS VALUES (4, 'Yes');
INSERT INTO DONATIONS VALUES ('444444',100,'A',0,3);
INSERT INTO DONATIONS VALUES ('555555',100,'C',0,3);
INSERT INTO DONATIONS VALUES ('666666',100,'C',0,4);
COMMIT;
END;
--ORA-12008: error in materialized view refresh path
--ORA-01476: divisor is equal to zero
--ORA-06512: at line 7

Note - it's entiirely possible to get more creative than 1/0 - you can put a User Defined Function that throws a comprehensible EXCEPTION instead.

OTHER TIPS

It looks like what you have here is a modelling problem. If document reference must be unique to a particular sponsor then it should be in its own table with a foreign key to sponsor, and the donation table should have a foreign key to the document reference table.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top