How to create trigger or procedure in Oracle express to automate values in a column of a table












0















How can I enter the value in the line_total column that would be made by the account (sales_line.line_total = product.unit_price * sales_line.line_qty)?



I would like to have trigger or a procedure to automate this. When I enter the values in the columns, it automatically triggers the trigger, doing that calculation and inserting the result in the column sales_line.line_total.



I would also like to automate the column sale.sale_total which would be the sum of the values column sales_line.line_total. Can you make a trigger or procedure for these two questions?



can you help me?



CREATE TABLE product (
product_id NUMBER(4) NOT NULL,
category_id NUMBER(4) NOT NULL,
p_desc VARCHAR2(40),
cpu VARCHAR2(14),
ram VARCHAR2(14),
capacity VARCHAR2(14),
screen_size VARCHAR2(14),
battery VARCHAR2(14),
unit_price NUMBER(7, 2),
colour VARCHAR2(14),
qty_stock NUMBER(4)
);
ALTER TABLE product ADD CONSTRAINT product_pk PRIMARY KEY ( product_id );

CREATE TABLE sale (
sale_id NUMBER(4) NOT NULL,
sale_date DATE,
customer_id NUMBER(4) NOT NULL,
employee_id NUMBER(4) NOT NULL,
sale_total NUMBER(7, 2)
);

ALTER TABLE sale ADD CONSTRAINT sale_pk PRIMARY KEY ( sale_id );

CREATE TABLE sales_line (
sale_id NUMBER(4) NOT NULL,
product_id NUMBER(4) NOT NULL,
line_qty NUMBER(4),
line_total NUMBER(7, 2)
);

ALTER TABLE sales_line ADD CONSTRAINT index_3 PRIMARY KEY ( sale_id,
product_id );

ALTER TABLE product
ADD CONSTRAINT product_p_category_fk FOREIGN KEY ( category_id )
REFERENCES p_category ( category_id );

ALTER TABLE sale
ADD CONSTRAINT sale_customer_fk FOREIGN KEY ( customer_id )
REFERENCES customer ( customer_id );

ALTER TABLE sale
ADD CONSTRAINT sale_employee_id_fk FOREIGN KEY ( employee_id )
REFERENCES employee ( employee_id );

ALTER TABLE sales_line
ADD CONSTRAINT sales_line_product_fk FOREIGN KEY ( product_id )
REFERENCES product ( product_id );

ALTER TABLE sales_line
ADD CONSTRAINT sales_line_sale_fk FOREIGN KEY ( sale_id )
REFERENCES sale ( sale_id );


Here are the triggers I have written so far:



CREATE OR REPLACE TRIGGER trg_line_total_ai AFTER INSERT OR UPDATE ON sales_line
FOR EACH ROW
DECLARE
lt_value NUMBER(7,2);
BEGIN
SELECT product.unit_price INTO lt_value FROM product;
UPDATE sales_line
SET line_total = :NEW.line_qty * lt_value
-- SET line_total = (line_qty * :NEW.unit_price)
WHERE product_id = :NEW.product_id;

--UPDATE sales_line
-- SET line_total = (line_qty * :OLD.unit_price)
--WHERE product.product_id = :OLD.product_id;
END;


CREATE OR REPLACE TRIGGER trg_sale_total_ai AFTER INSERT OR UPDATE ON sales_line
FOR EACH ROW
BEGIN
UPDATE sale
SET sale_total = (sale_total + :NEW.line_total)
WHERE sale_id = :NEW.sale_id;

UPDATE sale
SET sale_total = (sale_total + :OLD.line_total)
WHERE sale_id = :OLD.sale_id;
END;









share|improve this question




















  • 1





    Storing totals normally goes against all normalisation “rules”

    – Raymond Nijland
    Jan 1 at 13:41
















0















How can I enter the value in the line_total column that would be made by the account (sales_line.line_total = product.unit_price * sales_line.line_qty)?



I would like to have trigger or a procedure to automate this. When I enter the values in the columns, it automatically triggers the trigger, doing that calculation and inserting the result in the column sales_line.line_total.



I would also like to automate the column sale.sale_total which would be the sum of the values column sales_line.line_total. Can you make a trigger or procedure for these two questions?



can you help me?



CREATE TABLE product (
product_id NUMBER(4) NOT NULL,
category_id NUMBER(4) NOT NULL,
p_desc VARCHAR2(40),
cpu VARCHAR2(14),
ram VARCHAR2(14),
capacity VARCHAR2(14),
screen_size VARCHAR2(14),
battery VARCHAR2(14),
unit_price NUMBER(7, 2),
colour VARCHAR2(14),
qty_stock NUMBER(4)
);
ALTER TABLE product ADD CONSTRAINT product_pk PRIMARY KEY ( product_id );

CREATE TABLE sale (
sale_id NUMBER(4) NOT NULL,
sale_date DATE,
customer_id NUMBER(4) NOT NULL,
employee_id NUMBER(4) NOT NULL,
sale_total NUMBER(7, 2)
);

ALTER TABLE sale ADD CONSTRAINT sale_pk PRIMARY KEY ( sale_id );

CREATE TABLE sales_line (
sale_id NUMBER(4) NOT NULL,
product_id NUMBER(4) NOT NULL,
line_qty NUMBER(4),
line_total NUMBER(7, 2)
);

ALTER TABLE sales_line ADD CONSTRAINT index_3 PRIMARY KEY ( sale_id,
product_id );

ALTER TABLE product
ADD CONSTRAINT product_p_category_fk FOREIGN KEY ( category_id )
REFERENCES p_category ( category_id );

ALTER TABLE sale
ADD CONSTRAINT sale_customer_fk FOREIGN KEY ( customer_id )
REFERENCES customer ( customer_id );

ALTER TABLE sale
ADD CONSTRAINT sale_employee_id_fk FOREIGN KEY ( employee_id )
REFERENCES employee ( employee_id );

ALTER TABLE sales_line
ADD CONSTRAINT sales_line_product_fk FOREIGN KEY ( product_id )
REFERENCES product ( product_id );

ALTER TABLE sales_line
ADD CONSTRAINT sales_line_sale_fk FOREIGN KEY ( sale_id )
REFERENCES sale ( sale_id );


Here are the triggers I have written so far:



CREATE OR REPLACE TRIGGER trg_line_total_ai AFTER INSERT OR UPDATE ON sales_line
FOR EACH ROW
DECLARE
lt_value NUMBER(7,2);
BEGIN
SELECT product.unit_price INTO lt_value FROM product;
UPDATE sales_line
SET line_total = :NEW.line_qty * lt_value
-- SET line_total = (line_qty * :NEW.unit_price)
WHERE product_id = :NEW.product_id;

--UPDATE sales_line
-- SET line_total = (line_qty * :OLD.unit_price)
--WHERE product.product_id = :OLD.product_id;
END;


CREATE OR REPLACE TRIGGER trg_sale_total_ai AFTER INSERT OR UPDATE ON sales_line
FOR EACH ROW
BEGIN
UPDATE sale
SET sale_total = (sale_total + :NEW.line_total)
WHERE sale_id = :NEW.sale_id;

UPDATE sale
SET sale_total = (sale_total + :OLD.line_total)
WHERE sale_id = :OLD.sale_id;
END;









share|improve this question




















  • 1





    Storing totals normally goes against all normalisation “rules”

    – Raymond Nijland
    Jan 1 at 13:41














0












0








0








How can I enter the value in the line_total column that would be made by the account (sales_line.line_total = product.unit_price * sales_line.line_qty)?



I would like to have trigger or a procedure to automate this. When I enter the values in the columns, it automatically triggers the trigger, doing that calculation and inserting the result in the column sales_line.line_total.



I would also like to automate the column sale.sale_total which would be the sum of the values column sales_line.line_total. Can you make a trigger or procedure for these two questions?



can you help me?



CREATE TABLE product (
product_id NUMBER(4) NOT NULL,
category_id NUMBER(4) NOT NULL,
p_desc VARCHAR2(40),
cpu VARCHAR2(14),
ram VARCHAR2(14),
capacity VARCHAR2(14),
screen_size VARCHAR2(14),
battery VARCHAR2(14),
unit_price NUMBER(7, 2),
colour VARCHAR2(14),
qty_stock NUMBER(4)
);
ALTER TABLE product ADD CONSTRAINT product_pk PRIMARY KEY ( product_id );

CREATE TABLE sale (
sale_id NUMBER(4) NOT NULL,
sale_date DATE,
customer_id NUMBER(4) NOT NULL,
employee_id NUMBER(4) NOT NULL,
sale_total NUMBER(7, 2)
);

ALTER TABLE sale ADD CONSTRAINT sale_pk PRIMARY KEY ( sale_id );

CREATE TABLE sales_line (
sale_id NUMBER(4) NOT NULL,
product_id NUMBER(4) NOT NULL,
line_qty NUMBER(4),
line_total NUMBER(7, 2)
);

ALTER TABLE sales_line ADD CONSTRAINT index_3 PRIMARY KEY ( sale_id,
product_id );

ALTER TABLE product
ADD CONSTRAINT product_p_category_fk FOREIGN KEY ( category_id )
REFERENCES p_category ( category_id );

ALTER TABLE sale
ADD CONSTRAINT sale_customer_fk FOREIGN KEY ( customer_id )
REFERENCES customer ( customer_id );

ALTER TABLE sale
ADD CONSTRAINT sale_employee_id_fk FOREIGN KEY ( employee_id )
REFERENCES employee ( employee_id );

ALTER TABLE sales_line
ADD CONSTRAINT sales_line_product_fk FOREIGN KEY ( product_id )
REFERENCES product ( product_id );

ALTER TABLE sales_line
ADD CONSTRAINT sales_line_sale_fk FOREIGN KEY ( sale_id )
REFERENCES sale ( sale_id );


Here are the triggers I have written so far:



CREATE OR REPLACE TRIGGER trg_line_total_ai AFTER INSERT OR UPDATE ON sales_line
FOR EACH ROW
DECLARE
lt_value NUMBER(7,2);
BEGIN
SELECT product.unit_price INTO lt_value FROM product;
UPDATE sales_line
SET line_total = :NEW.line_qty * lt_value
-- SET line_total = (line_qty * :NEW.unit_price)
WHERE product_id = :NEW.product_id;

--UPDATE sales_line
-- SET line_total = (line_qty * :OLD.unit_price)
--WHERE product.product_id = :OLD.product_id;
END;


CREATE OR REPLACE TRIGGER trg_sale_total_ai AFTER INSERT OR UPDATE ON sales_line
FOR EACH ROW
BEGIN
UPDATE sale
SET sale_total = (sale_total + :NEW.line_total)
WHERE sale_id = :NEW.sale_id;

UPDATE sale
SET sale_total = (sale_total + :OLD.line_total)
WHERE sale_id = :OLD.sale_id;
END;









share|improve this question
















How can I enter the value in the line_total column that would be made by the account (sales_line.line_total = product.unit_price * sales_line.line_qty)?



I would like to have trigger or a procedure to automate this. When I enter the values in the columns, it automatically triggers the trigger, doing that calculation and inserting the result in the column sales_line.line_total.



I would also like to automate the column sale.sale_total which would be the sum of the values column sales_line.line_total. Can you make a trigger or procedure for these two questions?



can you help me?



CREATE TABLE product (
product_id NUMBER(4) NOT NULL,
category_id NUMBER(4) NOT NULL,
p_desc VARCHAR2(40),
cpu VARCHAR2(14),
ram VARCHAR2(14),
capacity VARCHAR2(14),
screen_size VARCHAR2(14),
battery VARCHAR2(14),
unit_price NUMBER(7, 2),
colour VARCHAR2(14),
qty_stock NUMBER(4)
);
ALTER TABLE product ADD CONSTRAINT product_pk PRIMARY KEY ( product_id );

CREATE TABLE sale (
sale_id NUMBER(4) NOT NULL,
sale_date DATE,
customer_id NUMBER(4) NOT NULL,
employee_id NUMBER(4) NOT NULL,
sale_total NUMBER(7, 2)
);

ALTER TABLE sale ADD CONSTRAINT sale_pk PRIMARY KEY ( sale_id );

CREATE TABLE sales_line (
sale_id NUMBER(4) NOT NULL,
product_id NUMBER(4) NOT NULL,
line_qty NUMBER(4),
line_total NUMBER(7, 2)
);

ALTER TABLE sales_line ADD CONSTRAINT index_3 PRIMARY KEY ( sale_id,
product_id );

ALTER TABLE product
ADD CONSTRAINT product_p_category_fk FOREIGN KEY ( category_id )
REFERENCES p_category ( category_id );

ALTER TABLE sale
ADD CONSTRAINT sale_customer_fk FOREIGN KEY ( customer_id )
REFERENCES customer ( customer_id );

ALTER TABLE sale
ADD CONSTRAINT sale_employee_id_fk FOREIGN KEY ( employee_id )
REFERENCES employee ( employee_id );

ALTER TABLE sales_line
ADD CONSTRAINT sales_line_product_fk FOREIGN KEY ( product_id )
REFERENCES product ( product_id );

ALTER TABLE sales_line
ADD CONSTRAINT sales_line_sale_fk FOREIGN KEY ( sale_id )
REFERENCES sale ( sale_id );


Here are the triggers I have written so far:



CREATE OR REPLACE TRIGGER trg_line_total_ai AFTER INSERT OR UPDATE ON sales_line
FOR EACH ROW
DECLARE
lt_value NUMBER(7,2);
BEGIN
SELECT product.unit_price INTO lt_value FROM product;
UPDATE sales_line
SET line_total = :NEW.line_qty * lt_value
-- SET line_total = (line_qty * :NEW.unit_price)
WHERE product_id = :NEW.product_id;

--UPDATE sales_line
-- SET line_total = (line_qty * :OLD.unit_price)
--WHERE product.product_id = :OLD.product_id;
END;


CREATE OR REPLACE TRIGGER trg_sale_total_ai AFTER INSERT OR UPDATE ON sales_line
FOR EACH ROW
BEGIN
UPDATE sale
SET sale_total = (sale_total + :NEW.line_total)
WHERE sale_id = :NEW.sale_id;

UPDATE sale
SET sale_total = (sale_total + :OLD.line_total)
WHERE sale_id = :OLD.sale_id;
END;






sql oracle database-trigger






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 1 at 13:32









APC

119k15118229




119k15118229










asked Jan 1 at 3:59









DVigaDViga

276




276








  • 1





    Storing totals normally goes against all normalisation “rules”

    – Raymond Nijland
    Jan 1 at 13:41














  • 1





    Storing totals normally goes against all normalisation “rules”

    – Raymond Nijland
    Jan 1 at 13:41








1




1





Storing totals normally goes against all normalisation “rules”

– Raymond Nijland
Jan 1 at 13:41





Storing totals normally goes against all normalisation “rules”

– Raymond Nijland
Jan 1 at 13:41












3 Answers
3






active

oldest

votes


















0














You have major two issues. The first (as noted in other answers) is that the first trigger should be a before trigger that modifies the records in place. The logic for the trigger can also be simplified (as below)



The second issues is that you should be subtracting the old values in the second trigger. So:



CREATE OR REPLACE TRIGGER trg_line_total_ai
BEFORE INSERT OR UPDATE ON sales_line
FOR EACH ROW
BEGIN
SELECT :NEW.line_qty * p.unit_price
INTO :NEW.line_total
FROM product p
WHERE p.product_id = :NEW.product_id;
END;


CREATE OR REPLACE TRIGGER trg_sale_total_ai
AFTER INSERT OR UPDATE ON sales_line
FOR EACH ROW
BEGIN
UPDATE sale
SET sale_total = (sale_total + :NEW.line_total)
WHERE sale_id = :NEW.sale_id;

UPDATE sale
SET sale_total = (sale_total - :OLD.line_total)
WHERE sale_id = :OLD.sale_id;
END;


Note that the second trigger has two updates. This allows the sale_id to be updated. You can wrap this into a single update if you like:



    UPDATE sale     
SET sale_total = (sale_total +
(CASE WHEN sale_id = :NEW.sale_id THEN :NEW.line_total ELSE 0 END) -
(CASE WHEN sale_id = :OLD.sale_id THEN :OLD.line_total ELSE 0 END)
)
WHERE sale_id IN (:OLD.sale_id, :NEW.sale_id);


You need to be very careful with expressing this logic so it works for both updates and inserts. You should probably extend this trigger to work for deletes as well.






share|improve this answer
























  • INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0) Error report - SQL Error: ORA-04098: trigger 'SYSTEM.TRG_LINE_TOTAL_BIU' is invalid and failed re-validation 04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation" *Cause: A trigger was attempted to be retrieved for execution and was found to be invalid. This also means that compilation/authorization failed for the trigger. *Action: Options are to resolve the compilation/authorization errors, disable the trigger, or drop the trigger.

    – DViga
    Jan 1 at 15:09













  • Thank everyone and Gordon Linoff for help me. I tried, but it return that error. I'm new here. So, sorry for some mistakes. Can you tell me how fix that error? Happy New Year. I'm tried do that for some days.

    – DViga
    Jan 1 at 15:15













  • @DViga . . . Neither of these triggers is called TRG_LINE_TOTAL_BIU. That error can happen when the queries in the trigger cannot be recompiled -- often because of a mistake in a column or table name. You need to double check the queries to be sure they are correct. They look correct.

    – Gordon Linoff
    Jan 1 at 15:18











  • APC and @Gordon Linoff I did exactly as Gordon put that, and I checked and the error is the same. And I removed the UPDATE and put BEFORE instead AFTER. Could be, something about the sale_id and product_id in the sales_line table be (PF) - composite keys? Because I don't understand where the error I just put the insert code: INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0). Can you guys help me please? I put the tables above, so the column names and set-up is ok with the insert code.

    – DViga
    Jan 1 at 15:43











  • @DViga . . . Unfortunately, the online sites that allow testing of code don't seem to work for Oracle SQL with triggers. That makes it hard to figure out what is happening. I wonder if there is some sort of permissions issue when revalidating the trigger.

    – Gordon Linoff
    Jan 1 at 15:53



















0














To update sale_line you must use a before trigger, then update is not necesary over this table. Only asign value to :New.line_total.
To update sale you can do it in the dame trigger.






share|improve this answer
























  • Thank you for reply, but I didn't understand what means. Can you show me please? Thank you

    – DViga
    Jan 1 at 4:40



















0














Use following code instead. Please note the keyword "Before" instead of After in both triggers definitions



CREATE OR REPLACE TRIGGER trg_line_total_ai BEFORE INSERT OR UPDATE ON sales_line
FOR EACH ROW
DECLARE
lt_value NUMBER(7,2);
BEGIN
SELECT product.unit_price INTO lt_value FROM product;
UPDATE sales_line
SET line_total = :NEW.line_qty * lt_value
-- SET line_total = (line_qty * :NEW.unit_price)
WHERE product_id = :NEW.product_id;

--UPDATE sales_line
-- SET line_total = (line_qty * :OLD.unit_price)
--WHERE product.product_id = :OLD.product_id;
END;


CREATE OR REPLACE TRIGGER trg_sale_total_ai BEFORE INSERT OR UPDATE ON sales_line
FOR EACH ROW
BEGIN
UPDATE sale
SET sale_total = (sale_total + :NEW.line_total)
WHERE sale_id = :NEW.sale_id;

UPDATE sale
SET sale_total = (sale_total + :OLD.line_total)
WHERE sale_id = :OLD.sale_id;
END;





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53992920%2fhow-to-create-trigger-or-procedure-in-oracle-express-to-automate-values-in-a-col%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    You have major two issues. The first (as noted in other answers) is that the first trigger should be a before trigger that modifies the records in place. The logic for the trigger can also be simplified (as below)



    The second issues is that you should be subtracting the old values in the second trigger. So:



    CREATE OR REPLACE TRIGGER trg_line_total_ai
    BEFORE INSERT OR UPDATE ON sales_line
    FOR EACH ROW
    BEGIN
    SELECT :NEW.line_qty * p.unit_price
    INTO :NEW.line_total
    FROM product p
    WHERE p.product_id = :NEW.product_id;
    END;


    CREATE OR REPLACE TRIGGER trg_sale_total_ai
    AFTER INSERT OR UPDATE ON sales_line
    FOR EACH ROW
    BEGIN
    UPDATE sale
    SET sale_total = (sale_total + :NEW.line_total)
    WHERE sale_id = :NEW.sale_id;

    UPDATE sale
    SET sale_total = (sale_total - :OLD.line_total)
    WHERE sale_id = :OLD.sale_id;
    END;


    Note that the second trigger has two updates. This allows the sale_id to be updated. You can wrap this into a single update if you like:



        UPDATE sale     
    SET sale_total = (sale_total +
    (CASE WHEN sale_id = :NEW.sale_id THEN :NEW.line_total ELSE 0 END) -
    (CASE WHEN sale_id = :OLD.sale_id THEN :OLD.line_total ELSE 0 END)
    )
    WHERE sale_id IN (:OLD.sale_id, :NEW.sale_id);


    You need to be very careful with expressing this logic so it works for both updates and inserts. You should probably extend this trigger to work for deletes as well.






    share|improve this answer
























    • INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0) Error report - SQL Error: ORA-04098: trigger 'SYSTEM.TRG_LINE_TOTAL_BIU' is invalid and failed re-validation 04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation" *Cause: A trigger was attempted to be retrieved for execution and was found to be invalid. This also means that compilation/authorization failed for the trigger. *Action: Options are to resolve the compilation/authorization errors, disable the trigger, or drop the trigger.

      – DViga
      Jan 1 at 15:09













    • Thank everyone and Gordon Linoff for help me. I tried, but it return that error. I'm new here. So, sorry for some mistakes. Can you tell me how fix that error? Happy New Year. I'm tried do that for some days.

      – DViga
      Jan 1 at 15:15













    • @DViga . . . Neither of these triggers is called TRG_LINE_TOTAL_BIU. That error can happen when the queries in the trigger cannot be recompiled -- often because of a mistake in a column or table name. You need to double check the queries to be sure they are correct. They look correct.

      – Gordon Linoff
      Jan 1 at 15:18











    • APC and @Gordon Linoff I did exactly as Gordon put that, and I checked and the error is the same. And I removed the UPDATE and put BEFORE instead AFTER. Could be, something about the sale_id and product_id in the sales_line table be (PF) - composite keys? Because I don't understand where the error I just put the insert code: INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0). Can you guys help me please? I put the tables above, so the column names and set-up is ok with the insert code.

      – DViga
      Jan 1 at 15:43











    • @DViga . . . Unfortunately, the online sites that allow testing of code don't seem to work for Oracle SQL with triggers. That makes it hard to figure out what is happening. I wonder if there is some sort of permissions issue when revalidating the trigger.

      – Gordon Linoff
      Jan 1 at 15:53
















    0














    You have major two issues. The first (as noted in other answers) is that the first trigger should be a before trigger that modifies the records in place. The logic for the trigger can also be simplified (as below)



    The second issues is that you should be subtracting the old values in the second trigger. So:



    CREATE OR REPLACE TRIGGER trg_line_total_ai
    BEFORE INSERT OR UPDATE ON sales_line
    FOR EACH ROW
    BEGIN
    SELECT :NEW.line_qty * p.unit_price
    INTO :NEW.line_total
    FROM product p
    WHERE p.product_id = :NEW.product_id;
    END;


    CREATE OR REPLACE TRIGGER trg_sale_total_ai
    AFTER INSERT OR UPDATE ON sales_line
    FOR EACH ROW
    BEGIN
    UPDATE sale
    SET sale_total = (sale_total + :NEW.line_total)
    WHERE sale_id = :NEW.sale_id;

    UPDATE sale
    SET sale_total = (sale_total - :OLD.line_total)
    WHERE sale_id = :OLD.sale_id;
    END;


    Note that the second trigger has two updates. This allows the sale_id to be updated. You can wrap this into a single update if you like:



        UPDATE sale     
    SET sale_total = (sale_total +
    (CASE WHEN sale_id = :NEW.sale_id THEN :NEW.line_total ELSE 0 END) -
    (CASE WHEN sale_id = :OLD.sale_id THEN :OLD.line_total ELSE 0 END)
    )
    WHERE sale_id IN (:OLD.sale_id, :NEW.sale_id);


    You need to be very careful with expressing this logic so it works for both updates and inserts. You should probably extend this trigger to work for deletes as well.






    share|improve this answer
























    • INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0) Error report - SQL Error: ORA-04098: trigger 'SYSTEM.TRG_LINE_TOTAL_BIU' is invalid and failed re-validation 04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation" *Cause: A trigger was attempted to be retrieved for execution and was found to be invalid. This also means that compilation/authorization failed for the trigger. *Action: Options are to resolve the compilation/authorization errors, disable the trigger, or drop the trigger.

      – DViga
      Jan 1 at 15:09













    • Thank everyone and Gordon Linoff for help me. I tried, but it return that error. I'm new here. So, sorry for some mistakes. Can you tell me how fix that error? Happy New Year. I'm tried do that for some days.

      – DViga
      Jan 1 at 15:15













    • @DViga . . . Neither of these triggers is called TRG_LINE_TOTAL_BIU. That error can happen when the queries in the trigger cannot be recompiled -- often because of a mistake in a column or table name. You need to double check the queries to be sure they are correct. They look correct.

      – Gordon Linoff
      Jan 1 at 15:18











    • APC and @Gordon Linoff I did exactly as Gordon put that, and I checked and the error is the same. And I removed the UPDATE and put BEFORE instead AFTER. Could be, something about the sale_id and product_id in the sales_line table be (PF) - composite keys? Because I don't understand where the error I just put the insert code: INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0). Can you guys help me please? I put the tables above, so the column names and set-up is ok with the insert code.

      – DViga
      Jan 1 at 15:43











    • @DViga . . . Unfortunately, the online sites that allow testing of code don't seem to work for Oracle SQL with triggers. That makes it hard to figure out what is happening. I wonder if there is some sort of permissions issue when revalidating the trigger.

      – Gordon Linoff
      Jan 1 at 15:53














    0












    0








    0







    You have major two issues. The first (as noted in other answers) is that the first trigger should be a before trigger that modifies the records in place. The logic for the trigger can also be simplified (as below)



    The second issues is that you should be subtracting the old values in the second trigger. So:



    CREATE OR REPLACE TRIGGER trg_line_total_ai
    BEFORE INSERT OR UPDATE ON sales_line
    FOR EACH ROW
    BEGIN
    SELECT :NEW.line_qty * p.unit_price
    INTO :NEW.line_total
    FROM product p
    WHERE p.product_id = :NEW.product_id;
    END;


    CREATE OR REPLACE TRIGGER trg_sale_total_ai
    AFTER INSERT OR UPDATE ON sales_line
    FOR EACH ROW
    BEGIN
    UPDATE sale
    SET sale_total = (sale_total + :NEW.line_total)
    WHERE sale_id = :NEW.sale_id;

    UPDATE sale
    SET sale_total = (sale_total - :OLD.line_total)
    WHERE sale_id = :OLD.sale_id;
    END;


    Note that the second trigger has two updates. This allows the sale_id to be updated. You can wrap this into a single update if you like:



        UPDATE sale     
    SET sale_total = (sale_total +
    (CASE WHEN sale_id = :NEW.sale_id THEN :NEW.line_total ELSE 0 END) -
    (CASE WHEN sale_id = :OLD.sale_id THEN :OLD.line_total ELSE 0 END)
    )
    WHERE sale_id IN (:OLD.sale_id, :NEW.sale_id);


    You need to be very careful with expressing this logic so it works for both updates and inserts. You should probably extend this trigger to work for deletes as well.






    share|improve this answer













    You have major two issues. The first (as noted in other answers) is that the first trigger should be a before trigger that modifies the records in place. The logic for the trigger can also be simplified (as below)



    The second issues is that you should be subtracting the old values in the second trigger. So:



    CREATE OR REPLACE TRIGGER trg_line_total_ai
    BEFORE INSERT OR UPDATE ON sales_line
    FOR EACH ROW
    BEGIN
    SELECT :NEW.line_qty * p.unit_price
    INTO :NEW.line_total
    FROM product p
    WHERE p.product_id = :NEW.product_id;
    END;


    CREATE OR REPLACE TRIGGER trg_sale_total_ai
    AFTER INSERT OR UPDATE ON sales_line
    FOR EACH ROW
    BEGIN
    UPDATE sale
    SET sale_total = (sale_total + :NEW.line_total)
    WHERE sale_id = :NEW.sale_id;

    UPDATE sale
    SET sale_total = (sale_total - :OLD.line_total)
    WHERE sale_id = :OLD.sale_id;
    END;


    Note that the second trigger has two updates. This allows the sale_id to be updated. You can wrap this into a single update if you like:



        UPDATE sale     
    SET sale_total = (sale_total +
    (CASE WHEN sale_id = :NEW.sale_id THEN :NEW.line_total ELSE 0 END) -
    (CASE WHEN sale_id = :OLD.sale_id THEN :OLD.line_total ELSE 0 END)
    )
    WHERE sale_id IN (:OLD.sale_id, :NEW.sale_id);


    You need to be very careful with expressing this logic so it works for both updates and inserts. You should probably extend this trigger to work for deletes as well.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Jan 1 at 13:35









    Gordon LinoffGordon Linoff

    776k35306409




    776k35306409













    • INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0) Error report - SQL Error: ORA-04098: trigger 'SYSTEM.TRG_LINE_TOTAL_BIU' is invalid and failed re-validation 04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation" *Cause: A trigger was attempted to be retrieved for execution and was found to be invalid. This also means that compilation/authorization failed for the trigger. *Action: Options are to resolve the compilation/authorization errors, disable the trigger, or drop the trigger.

      – DViga
      Jan 1 at 15:09













    • Thank everyone and Gordon Linoff for help me. I tried, but it return that error. I'm new here. So, sorry for some mistakes. Can you tell me how fix that error? Happy New Year. I'm tried do that for some days.

      – DViga
      Jan 1 at 15:15













    • @DViga . . . Neither of these triggers is called TRG_LINE_TOTAL_BIU. That error can happen when the queries in the trigger cannot be recompiled -- often because of a mistake in a column or table name. You need to double check the queries to be sure they are correct. They look correct.

      – Gordon Linoff
      Jan 1 at 15:18











    • APC and @Gordon Linoff I did exactly as Gordon put that, and I checked and the error is the same. And I removed the UPDATE and put BEFORE instead AFTER. Could be, something about the sale_id and product_id in the sales_line table be (PF) - composite keys? Because I don't understand where the error I just put the insert code: INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0). Can you guys help me please? I put the tables above, so the column names and set-up is ok with the insert code.

      – DViga
      Jan 1 at 15:43











    • @DViga . . . Unfortunately, the online sites that allow testing of code don't seem to work for Oracle SQL with triggers. That makes it hard to figure out what is happening. I wonder if there is some sort of permissions issue when revalidating the trigger.

      – Gordon Linoff
      Jan 1 at 15:53



















    • INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0) Error report - SQL Error: ORA-04098: trigger 'SYSTEM.TRG_LINE_TOTAL_BIU' is invalid and failed re-validation 04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation" *Cause: A trigger was attempted to be retrieved for execution and was found to be invalid. This also means that compilation/authorization failed for the trigger. *Action: Options are to resolve the compilation/authorization errors, disable the trigger, or drop the trigger.

      – DViga
      Jan 1 at 15:09













    • Thank everyone and Gordon Linoff for help me. I tried, but it return that error. I'm new here. So, sorry for some mistakes. Can you tell me how fix that error? Happy New Year. I'm tried do that for some days.

      – DViga
      Jan 1 at 15:15













    • @DViga . . . Neither of these triggers is called TRG_LINE_TOTAL_BIU. That error can happen when the queries in the trigger cannot be recompiled -- often because of a mistake in a column or table name. You need to double check the queries to be sure they are correct. They look correct.

      – Gordon Linoff
      Jan 1 at 15:18











    • APC and @Gordon Linoff I did exactly as Gordon put that, and I checked and the error is the same. And I removed the UPDATE and put BEFORE instead AFTER. Could be, something about the sale_id and product_id in the sales_line table be (PF) - composite keys? Because I don't understand where the error I just put the insert code: INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0). Can you guys help me please? I put the tables above, so the column names and set-up is ok with the insert code.

      – DViga
      Jan 1 at 15:43











    • @DViga . . . Unfortunately, the online sites that allow testing of code don't seem to work for Oracle SQL with triggers. That makes it hard to figure out what is happening. I wonder if there is some sort of permissions issue when revalidating the trigger.

      – Gordon Linoff
      Jan 1 at 15:53

















    INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0) Error report - SQL Error: ORA-04098: trigger 'SYSTEM.TRG_LINE_TOTAL_BIU' is invalid and failed re-validation 04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation" *Cause: A trigger was attempted to be retrieved for execution and was found to be invalid. This also means that compilation/authorization failed for the trigger. *Action: Options are to resolve the compilation/authorization errors, disable the trigger, or drop the trigger.

    – DViga
    Jan 1 at 15:09







    INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0) Error report - SQL Error: ORA-04098: trigger 'SYSTEM.TRG_LINE_TOTAL_BIU' is invalid and failed re-validation 04098. 00000 - "trigger '%s.%s' is invalid and failed re-validation" *Cause: A trigger was attempted to be retrieved for execution and was found to be invalid. This also means that compilation/authorization failed for the trigger. *Action: Options are to resolve the compilation/authorization errors, disable the trigger, or drop the trigger.

    – DViga
    Jan 1 at 15:09















    Thank everyone and Gordon Linoff for help me. I tried, but it return that error. I'm new here. So, sorry for some mistakes. Can you tell me how fix that error? Happy New Year. I'm tried do that for some days.

    – DViga
    Jan 1 at 15:15







    Thank everyone and Gordon Linoff for help me. I tried, but it return that error. I'm new here. So, sorry for some mistakes. Can you tell me how fix that error? Happy New Year. I'm tried do that for some days.

    – DViga
    Jan 1 at 15:15















    @DViga . . . Neither of these triggers is called TRG_LINE_TOTAL_BIU. That error can happen when the queries in the trigger cannot be recompiled -- often because of a mistake in a column or table name. You need to double check the queries to be sure they are correct. They look correct.

    – Gordon Linoff
    Jan 1 at 15:18





    @DViga . . . Neither of these triggers is called TRG_LINE_TOTAL_BIU. That error can happen when the queries in the trigger cannot be recompiled -- often because of a mistake in a column or table name. You need to double check the queries to be sure they are correct. They look correct.

    – Gordon Linoff
    Jan 1 at 15:18













    APC and @Gordon Linoff I did exactly as Gordon put that, and I checked and the error is the same. And I removed the UPDATE and put BEFORE instead AFTER. Could be, something about the sale_id and product_id in the sales_line table be (PF) - composite keys? Because I don't understand where the error I just put the insert code: INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0). Can you guys help me please? I put the tables above, so the column names and set-up is ok with the insert code.

    – DViga
    Jan 1 at 15:43





    APC and @Gordon Linoff I did exactly as Gordon put that, and I checked and the error is the same. And I removed the UPDATE and put BEFORE instead AFTER. Could be, something about the sale_id and product_id in the sales_line table be (PF) - composite keys? Because I don't understand where the error I just put the insert code: INSERT INTO sales_line (sale_id, product_id, line_qty, line_total) VALUES (2, 24, 1, 0). Can you guys help me please? I put the tables above, so the column names and set-up is ok with the insert code.

    – DViga
    Jan 1 at 15:43













    @DViga . . . Unfortunately, the online sites that allow testing of code don't seem to work for Oracle SQL with triggers. That makes it hard to figure out what is happening. I wonder if there is some sort of permissions issue when revalidating the trigger.

    – Gordon Linoff
    Jan 1 at 15:53





    @DViga . . . Unfortunately, the online sites that allow testing of code don't seem to work for Oracle SQL with triggers. That makes it hard to figure out what is happening. I wonder if there is some sort of permissions issue when revalidating the trigger.

    – Gordon Linoff
    Jan 1 at 15:53













    0














    To update sale_line you must use a before trigger, then update is not necesary over this table. Only asign value to :New.line_total.
    To update sale you can do it in the dame trigger.






    share|improve this answer
























    • Thank you for reply, but I didn't understand what means. Can you show me please? Thank you

      – DViga
      Jan 1 at 4:40
















    0














    To update sale_line you must use a before trigger, then update is not necesary over this table. Only asign value to :New.line_total.
    To update sale you can do it in the dame trigger.






    share|improve this answer
























    • Thank you for reply, but I didn't understand what means. Can you show me please? Thank you

      – DViga
      Jan 1 at 4:40














    0












    0








    0







    To update sale_line you must use a before trigger, then update is not necesary over this table. Only asign value to :New.line_total.
    To update sale you can do it in the dame trigger.






    share|improve this answer













    To update sale_line you must use a before trigger, then update is not necesary over this table. Only asign value to :New.line_total.
    To update sale you can do it in the dame trigger.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Jan 1 at 4:25









    lugolulugolu

    4615




    4615













    • Thank you for reply, but I didn't understand what means. Can you show me please? Thank you

      – DViga
      Jan 1 at 4:40



















    • Thank you for reply, but I didn't understand what means. Can you show me please? Thank you

      – DViga
      Jan 1 at 4:40

















    Thank you for reply, but I didn't understand what means. Can you show me please? Thank you

    – DViga
    Jan 1 at 4:40





    Thank you for reply, but I didn't understand what means. Can you show me please? Thank you

    – DViga
    Jan 1 at 4:40











    0














    Use following code instead. Please note the keyword "Before" instead of After in both triggers definitions



    CREATE OR REPLACE TRIGGER trg_line_total_ai BEFORE INSERT OR UPDATE ON sales_line
    FOR EACH ROW
    DECLARE
    lt_value NUMBER(7,2);
    BEGIN
    SELECT product.unit_price INTO lt_value FROM product;
    UPDATE sales_line
    SET line_total = :NEW.line_qty * lt_value
    -- SET line_total = (line_qty * :NEW.unit_price)
    WHERE product_id = :NEW.product_id;

    --UPDATE sales_line
    -- SET line_total = (line_qty * :OLD.unit_price)
    --WHERE product.product_id = :OLD.product_id;
    END;


    CREATE OR REPLACE TRIGGER trg_sale_total_ai BEFORE INSERT OR UPDATE ON sales_line
    FOR EACH ROW
    BEGIN
    UPDATE sale
    SET sale_total = (sale_total + :NEW.line_total)
    WHERE sale_id = :NEW.sale_id;

    UPDATE sale
    SET sale_total = (sale_total + :OLD.line_total)
    WHERE sale_id = :OLD.sale_id;
    END;





    share|improve this answer




























      0














      Use following code instead. Please note the keyword "Before" instead of After in both triggers definitions



      CREATE OR REPLACE TRIGGER trg_line_total_ai BEFORE INSERT OR UPDATE ON sales_line
      FOR EACH ROW
      DECLARE
      lt_value NUMBER(7,2);
      BEGIN
      SELECT product.unit_price INTO lt_value FROM product;
      UPDATE sales_line
      SET line_total = :NEW.line_qty * lt_value
      -- SET line_total = (line_qty * :NEW.unit_price)
      WHERE product_id = :NEW.product_id;

      --UPDATE sales_line
      -- SET line_total = (line_qty * :OLD.unit_price)
      --WHERE product.product_id = :OLD.product_id;
      END;


      CREATE OR REPLACE TRIGGER trg_sale_total_ai BEFORE INSERT OR UPDATE ON sales_line
      FOR EACH ROW
      BEGIN
      UPDATE sale
      SET sale_total = (sale_total + :NEW.line_total)
      WHERE sale_id = :NEW.sale_id;

      UPDATE sale
      SET sale_total = (sale_total + :OLD.line_total)
      WHERE sale_id = :OLD.sale_id;
      END;





      share|improve this answer


























        0












        0








        0







        Use following code instead. Please note the keyword "Before" instead of After in both triggers definitions



        CREATE OR REPLACE TRIGGER trg_line_total_ai BEFORE INSERT OR UPDATE ON sales_line
        FOR EACH ROW
        DECLARE
        lt_value NUMBER(7,2);
        BEGIN
        SELECT product.unit_price INTO lt_value FROM product;
        UPDATE sales_line
        SET line_total = :NEW.line_qty * lt_value
        -- SET line_total = (line_qty * :NEW.unit_price)
        WHERE product_id = :NEW.product_id;

        --UPDATE sales_line
        -- SET line_total = (line_qty * :OLD.unit_price)
        --WHERE product.product_id = :OLD.product_id;
        END;


        CREATE OR REPLACE TRIGGER trg_sale_total_ai BEFORE INSERT OR UPDATE ON sales_line
        FOR EACH ROW
        BEGIN
        UPDATE sale
        SET sale_total = (sale_total + :NEW.line_total)
        WHERE sale_id = :NEW.sale_id;

        UPDATE sale
        SET sale_total = (sale_total + :OLD.line_total)
        WHERE sale_id = :OLD.sale_id;
        END;





        share|improve this answer













        Use following code instead. Please note the keyword "Before" instead of After in both triggers definitions



        CREATE OR REPLACE TRIGGER trg_line_total_ai BEFORE INSERT OR UPDATE ON sales_line
        FOR EACH ROW
        DECLARE
        lt_value NUMBER(7,2);
        BEGIN
        SELECT product.unit_price INTO lt_value FROM product;
        UPDATE sales_line
        SET line_total = :NEW.line_qty * lt_value
        -- SET line_total = (line_qty * :NEW.unit_price)
        WHERE product_id = :NEW.product_id;

        --UPDATE sales_line
        -- SET line_total = (line_qty * :OLD.unit_price)
        --WHERE product.product_id = :OLD.product_id;
        END;


        CREATE OR REPLACE TRIGGER trg_sale_total_ai BEFORE INSERT OR UPDATE ON sales_line
        FOR EACH ROW
        BEGIN
        UPDATE sale
        SET sale_total = (sale_total + :NEW.line_total)
        WHERE sale_id = :NEW.sale_id;

        UPDATE sale
        SET sale_total = (sale_total + :OLD.line_total)
        WHERE sale_id = :OLD.sale_id;
        END;






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 1 at 12:59









        Rehan AliRehan Ali

        2415




        2415






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53992920%2fhow-to-create-trigger-or-procedure-in-oracle-express-to-automate-values-in-a-col%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Monofisismo

            Angular Downloading a file using contenturl with Basic Authentication

            Olmecas