Link to home
Start Free TrialLog in
Avatar of Eddie Shipman
Eddie ShipmanFlag for United States of America

asked on

Need help with "Upsert" trigger in Oracle

I have an Oracle table that contains 30 million records of a document archive that is built similar to an EAV table. It contains in each row an id, a keyword, and a value. There may be as a many as 10 records that make up one "document" entry.

 Queries to determine how many "documents" a person has in their archive take well over 30 seconds if they have a lot of documents, some take almost a minute.

I would like a trigger to insert a new record in the LIC_DOCCCOUNT table when a record with the keyword of CLRID is inserted and to decrement the DOUCCOUNT in the LIC_DOCCCOUNT with the same CLRID value when deleting, and I only want it to happen for certain CLRID values.

I'm not sure exactly how to create this trigger. Not a lot but here is what I have so far.

CREATE OR REPLACE TRIGGER trLIC_DOCCOUNT
    AFTER
        INSERT OR
        DELETE
    FOR EACH ROW
    ON fkp_attib
BEGIN
    -- Structure of LIC_DOCCOUNT Table:
    --  CLRID    NUMBER(10)  NOT NULL,
    --  DOC_COUNT  INTEGER
    -- FKP_VALUE has the value that we need to check for
    IF :New.fkp_keyword = 'CLRID' AND :New.fkp_value in (12345, 67890, 654123, 987456) THEN
        CASE
        WHEN INSERTING THEN
            -- this was an insert so insert a new record in LIC_DOCCOUNT 
            -- if a record with the same CLRID doesn't exist, otherwise, 
            -- update the record with the CLRID
        WHEN DELETING THEN
            -- decrement the DOC_COUNT for the record with the CLRID
        END CASE;
    END IF;
END;
/

Open in new window


Here's code we use to obtain the count:
select count(*) as DocCount from (
    select distinct doc.FKP_FD_RID 
    from fkp_attib doc, fkp_attib cli
    where doc.FKP_FD_RID=cli.FKP_FD_RID 
      and cli.FKP_KEYWORD='CLRID' and cli.FKP_VALUE = :PID group by doc.FKP_FD_RID
    having sum(decode(doc.fkp_keyword||doc.fkp_value,'DISTRIBUTIONINTERNAL',1,0))=0
    )

Open in new window

Avatar of slightwv (䄆 Netminder)
slightwv (䄆 Netminder)

With the distinct and having sum in the query, I can see where it might be inefficient.

I'm not fully understanding what you are trying to do.

Can you provide some sample raw data, some insert and deletes and expected results?
Avatar of Eddie Shipman

ASKER

Not sure how many records you need but here's 10 documents:
FKP_FD_RID	FKP_KEYWORD	FKP_VALUE
1621438	FILENAME	\1016713\770\Letters\CLDL20100302
1621438	CLRID		1016713
1621438	DOC_NAME	CLDL
1621438	PRINT_DATE	20100303
1621438	DESIGNATION	CISR
1621438	DISTRIBUTION	INTERNAL
1621439	FILENAME	\965699\603\Letters\CLDL20100302
1621439	CLI_RID		965699
1621439	DOC_NAME	CLDL
1621439	PRINT_DATE	20100303
1621439	DESIGNATION	CISR
1621439	DISTRIBUTION	INTERNAL
1621440	FILENAME	\1009723\759\Letters\CLDL20100302
1621440	CLI_RID		1009723
1621440	DOC_NAME	CLDL
1621440	PRINT_DATE	20100303
1621440	DESIGNATION	CISR
1621440	DISTRIBUTION	INTERNAL
1621441	FILENAME	\953310\178\Letters\CLDL20100302
1621441	CLI_RID		953310
1621441	DOC_NAME	CLDL
1621441	PRINT_DATE	20100303
1621441	DESIGNATION	CISR
1621441	DISTRIBUTION	INTERNAL
1621442	FILENAME	\1098748\54\Letters\CLDL20100302
1621442	CLI_RID		1098748
1621442	DOC_NAME	CLDL
1621442	PRINT_DATE	20100303
1621442	DESIGNATION	CISR
1621442	DISTRIBUTION	INTERNAL
1621443	FILENAME	\1088006\279\Letters\CLDL20100302
1621443	CLI_RID		1088006
1621443	DOC_NAME	CLDL
1621443	PRINT_DATE	20100303
1621443	DESIGNATION	CISR
1621443	DISTRIBUTION	INTERNAL
1621444	FILENAME	\996175\172\Letters\CLDL20100302
1621444	CLI_RID		996175
1621444	DOC_NAME	CLDL
1621444	PRINT_DATE	20100303
1621444	DESIGNATION	CISR
1621444	DISTRIBUTION	INTERNAL
1621445	FILENAME	\1092295\580\Letters\CLDL20100302
1621445	CLI_RID		1092295
1621445	DOC_NAME	CLDL
1621445	PRINT_DATE	20100303
1621445	DESIGNATION	CISR
1621445	DISTRIBUTION	INTERNAL
1621446	FILENAME	\900796\505\Letters\CLDL20100302
1621446	CLI_RID		900796
1621446	DOC_NAME	CLDL
1621446	PRINT_DATE	20100303
1621446	DESIGNATION	CISR
1621446	DISTRIBUTION	INTERNAL
1621447	FILENAME	\1091439\721\Letters\CLDL20100302
1621447	CLI_RID		1091439
1621447	DOC_NAME	CLDL
1621447	PRINT_DATE	20100303
1621447	DESIGNATION	CISR
1621447	DISTRIBUTION	INTERNAL
1621448	FILENAME	\921784\556\Letters\CLDL20100302
1621448	CLI_RID		921784
1621448	DOC_NAME	CLDL
1621448	PRINT_DATE	20100303
1621448	DESIGNATION	CISR
1621448	DISTRIBUTION	INTERNAL
1621449	FILENAME	\1113354\702\Letters\CLDL20100302
1621449	CLI_RID		1113354
1621449	DOC_NAME	CLDL
1621449	PRINT_DATE	20100303
1621449	DESIGNATION	CISR
1621449	DISTRIBUTION	INTERNAL

Open in new window



expected results would be just insert the number of documents for each CLRID in the list into the LIC_DOCCOUNT table.
Given your sample data, what would the LIC_DOCCOUNT table look like at that stage? Provide some data for, say, two inserts and select maybe three existing records for deletion, then show what the LIC_DOCCOUNT should look like after the trigger.
It is easy enough to write a insert and delete queries here, I don't need to provide those. The doc_ccount is based on the count of the CLRID value.

The contents of the LIC_DOCCOUNT table should look like this if my limiting CLRIDs are: 953310, 1092295, 1113354, 1016713:
CLRID       DOC_COUNT
1016713     1
953310      1
1092295     1
1113354     1

Open in new window


The other records that aren't in my limiting list do not get entries in the  table. The trigger only should work on the limiting list. However, the data provided includes the DISTRIBUTION keyword with a value of INTERNAL and those would be omitted from the count. Please use this revised data:
FKP_FD_RID	FKP_KEYWORD	FKP_VALUE
1621438	FILENAME	\1016713\770\Letters\CLDL20100302
1621438	CLRID		1016713
1621438	DOC_NAME	CLDL
1621438	PRINT_DATE	20100303
1621438	DESIGNATION	CISR
1621439	FILENAME	\965699\603\Letters\CLDL20100302
1621439	CLRID		965699
1621439	DOC_NAME	CLDL
1621439	PRINT_DATE	20100303
1621439	DESIGNATION	CISR
1621440	FILENAME	\1009723\759\Letters\CLDL20100302
1621440	CLRID		1009723
1621440	DOC_NAME	CLDL
1621440	PRINT_DATE	20100303
1621440	DESIGNATION	CISR
1621441	FILENAME	\953310\178\Letters\CLDL20100302
1621441	CLRID		953310
1621441	DOC_NAME	CLDL
1621441	PRINT_DATE	20100303
1621441	DESIGNATION	CISR
1621442	FILENAME	\1098748\54\Letters\CLDL20100302
1621442	CLRID		1098748
1621442	DOC_NAME	CLDL
1621442	PRINT_DATE	20100303
1621442	DESIGNATION	CISR
1621443	FILENAME	\1088006\279\Letters\CLDL20100302
1621443	CLRID		1088006
1621443	DOC_NAME	CLDL
1621443	PRINT_DATE	20100303
1621443	DESIGNATION	CISR
1621444	FILENAME	\996175\172\Letters\CLDL20100302
1621444	CLRID		996175
1621444	DOC_NAME	CLDL
1621444	PRINT_DATE	20100303
1621444	DESIGNATION	CISR
1621445	FILENAME	\1092295\580\Letters\CLDL20100302
1621445	CLRID		1092295
1621445	DOC_NAME	CLDL
1621445	PRINT_DATE	20100303
1621445	DESIGNATION	CISR
1621446	FILENAME	\900796\505\Letters\CLDL20100302
1621446	CLRID		900796
1621446	DOC_NAME	CLDL
1621446	PRINT_DATE	20100303
1621446	DESIGNATION	CISR
1621447	FILENAME	\1091439\721\Letters\CLDL20100302
1621447	CLRID		1091439
1621447	DOC_NAME	CLDL
1621447	PRINT_DATE	20100303
1621447	DESIGNATION	CISR
1621448	FILENAME	\921784\556\Letters\CLDL20100302
1621448	CLRID		921784
1621448	DOC_NAME	CLDL
1621448	PRINT_DATE	20100303
1621448	DESIGNATION	CISR
1621449	FILENAME	\1113354\702\Letters\CLDL20100302
1621449	CLRID		1113354
1621449	DOC_NAME	CLDL
1621449	PRINT_DATE	20100303
1621449	DESIGNATION	CISR

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of slightwv (䄆 Netminder)
slightwv (䄆 Netminder)

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Yeah, the initial code post didn't have the "filters" that matched the data I posted.
Hmm, never thought of that one, but it looks like it might work, let me work on it.

I will have to get an initial value to load the table to begin with, though.
>>I will have to get an initial value to load the table to begin with, though.

Should be a simple insert into as select statement.