How to create trigger or procedure in Oracle express to automate values in a column of a table
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
add a comment |
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
1
Storing totals normally goes against all normalisation “rules”
– Raymond Nijland
Jan 1 at 13:41
add a comment |
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
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
sql oracle database-trigger
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
add a comment |
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
add a comment |
3 Answers
3
active
oldest
votes
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 delete
s as well.
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 calledTRG_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
|
show 4 more comments
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.
Thank you for reply, but I didn't understand what means. Can you show me please? Thank you
– DViga
Jan 1 at 4:40
add a comment |
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;
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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 delete
s as well.
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 calledTRG_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
|
show 4 more comments
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 delete
s as well.
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 calledTRG_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
|
show 4 more comments
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 delete
s as well.
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 delete
s as well.
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 calledTRG_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
|
show 4 more comments
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 calledTRG_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
|
show 4 more comments
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.
Thank you for reply, but I didn't understand what means. Can you show me please? Thank you
– DViga
Jan 1 at 4:40
add a comment |
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.
Thank you for reply, but I didn't understand what means. Can you show me please? Thank you
– DViga
Jan 1 at 4:40
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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;
add a comment |
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;
add a comment |
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;
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;
answered Jan 1 at 12:59
Rehan AliRehan Ali
2415
2415
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
1
Storing totals normally goes against all normalisation “rules”
– Raymond Nijland
Jan 1 at 13:41