如何在 Oracle Express 中创建触发器或过程以自动执行 table 列中的值
How to create trigger or procedure in Oracle express to automate values in a column of a table
如何在 line_total
列中输入帐户 (sales_line.line_total = product.unit_price * sales_line.line_qty
) 生成的值?
我想要触发器或程序来自动执行此操作。当我在列中输入值时,它会自动触发触发器,进行计算并将结果插入列 sales_line.line_total
.
我还想自动化列 sale.sale_total
,它是值列 sales_line.line_total
的总和。你能为这两个问题做一个触发或程序吗?
你能帮帮我吗?
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 );
以下是我到目前为止编写的触发器:
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;
要更新 sale_line,您必须使用前触发器,然后不需要在此 table 上进行更新。只给 :New.line_total 赋值。
要更新销售,您可以在 dame 触发器中进行。
请改用以下代码。请注意关键字 "Before" 而不是两个触发器定义中的 After
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;
你有两个主要问题。第一个(如其他答案中所述)是第一个触发器应该是 before 触发器,用于修改适当的记录。触发器的逻辑也可以简化(如下)
第二个问题是您应该减去 第二个触发器中的old
值。所以:
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;
请注意,第二个触发器有两个更新。这允许更新 sale_id
。如果您愿意,您可以将其包装到一个更新中:
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);
您在表达此逻辑时需要非常小心,以便它适用于更新和插入。您或许应该扩展此触发器以使其也适用于 delete
s。
如何在 line_total
列中输入帐户 (sales_line.line_total = product.unit_price * sales_line.line_qty
) 生成的值?
我想要触发器或程序来自动执行此操作。当我在列中输入值时,它会自动触发触发器,进行计算并将结果插入列 sales_line.line_total
.
我还想自动化列 sale.sale_total
,它是值列 sales_line.line_total
的总和。你能为这两个问题做一个触发或程序吗?
你能帮帮我吗?
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 );
以下是我到目前为止编写的触发器:
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;
要更新 sale_line,您必须使用前触发器,然后不需要在此 table 上进行更新。只给 :New.line_total 赋值。 要更新销售,您可以在 dame 触发器中进行。
请改用以下代码。请注意关键字 "Before" 而不是两个触发器定义中的 After
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;
你有两个主要问题。第一个(如其他答案中所述)是第一个触发器应该是 before 触发器,用于修改适当的记录。触发器的逻辑也可以简化(如下)
第二个问题是您应该减去 第二个触发器中的old
值。所以:
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;
请注意,第二个触发器有两个更新。这允许更新 sale_id
。如果您愿意,您可以将其包装到一个更新中:
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);
您在表达此逻辑时需要非常小心,以便它适用于更新和插入。您或许应该扩展此触发器以使其也适用于 delete
s。