Oracle在插入后触发更新记录

时间:2014-04-19 13:18:40

标签: oracle plsql triggers

在将记录插入amount-1表后,我想要更新书籍集合sell

create table book (
id number(3) not null, 
name varchar(20),
author varchar(12),
amount number(3) not null,
constraint book_pk primary key(id)
);

create table sell (
id number(3) not null, 
date varchar(20),
book_id number(3),
constraint sell_pk primary key(id)
);

我想在插入表销售记录更新书表数量-1之后;

CREATE OR REPLACE TRIGER changes_amount_trigger
AFTER INSERT ON sell 
FOR EACH ROW
BEGIN

UPDATE BOOK SET amount = amount-1 WHERE id = book_id

END;

我不知道如何获取插入的记录簿ID,以更新书表中的此记录。

3 个答案:

答案 0 :(得分:3)

试试这个,

CREATE OR REPLACE TRIGGER changes_amount_trigger
AFTER INSERT ON sell 
FOR EACH ROW
BEGIN
     UPDATE BOOK SET amount = amount-1 WHERE id = :new.book_id;
END;
/

答案 1 :(得分:1)

数据模型假设:

我假设您将通过SELL表中的数据通过INSERT DML SQL操作来注册事务。您在SELL上设置DML触发器也可以支持这一点,以将其更改作为SALES信息传递给BOOK表。这是可行的。

偶然地,我尝试设置触发器的方式略有不同,我想建议一种不同的方法:

考虑可能在相反方向工作:直接在BOOK表上更改图书数量,因此只需购买一次book_id = 5即可处理以下查询:

    UPDATE book SET amount = amount -1
     WHERE id = 5;  COMMIT; 

补货意味着增加可用书籍的数量 通过递增AMOUNT值来代替。

还有一些其他更改可能会加强这种双表设计,并在长期内保护其中数据的完整性:

CREATE TABLE book (
    id number(3) not null, 
    name varchar(20),
    author varchar(12),
    amount number(3) not null,
    CONSTRAINT book_pk PRIMARY KEY(id)
    );


ALTER TABLE book
   ADD CONSTRAINT book_amt_ck CHECK (amount > 0);

ALTER TABLE book
   ENABLE CONSTRAINT book_amt_ck;

为防止负数账面金额(数量)值,TABLE CHECK CONSTRAINT将阻止在DML操作中通过算术错误输入值,例如:

    UPDATE book SET amount := amount - 1

在上面的示例中,即使手头的数量已达到0,也无法控制减少图书库存。请查看TABLE CHECK CONSTRAINTS上的一些参考资料,以便更好地了解它对特定内容的作用设计情况。

以下是触发器的一些设计建议:

  1. 图书数量的变化应该是影响SELL表格的唯一触发数据元素。

  2. 触发器应考虑到图书数量的变化> 1。

        CREATE OR REPLACE TRIGGER orders_after_update
            AFTER UPDATE
               ON book
              FOR EACH ROW
    
            DECLARE
              v_amount   number;
    
            BEGIN
    
            IF (:new.amount < :old.amount ) THEN
    
               FOR v_amount in  1 .. (:old.amount - :new.amount)
               LOOP
                  INSERT INTO sell (id, date, book_id)
                  VALUES (sell_seq.nextval, sysdate, :new.id);
    
                  COMMIT;
    
               END LOOP;
    
            END IF;
    
        END; 
    
  3. 有关触发器及其设计的更多信息,请查看几个实例,以便更好地了解它们的设计和设置方式。

        CREATE SEQUENCE sell_seq
           MINVALUE 1
           START WITH 1
           INCREMENT BY 1
           CACHE 20;
    

    我们需要一个序列来填充SELL表的主键/索引。 Oracle Sequences可用于此目的。

    通过使用BOOK表上的触发器观察表的更改,您可以使用表触发器触发时已存在的内置引用。例如,BOOK.ID不需要额外的查询,因为触发器会自动识别每个触发器监控记录的开始和结束值。

    有关触发器的一些有用讨论将在more detail中通过互联网搜索进行讨论。

    设置外键关系

    虽然触发器可能会保持这种关系干净,但元素BOOK.IDSELL.BOOK_ID之间的外键关系会很好,否则对销售交易的查询可能会产生图书销售而没有任何描述性的生产信息。以下是a reference on Foreign Keys及其使用方法。

    CREATE TABLE sell (
        id number(3) not null, 
        date varchar(20),
        book_id number(3)
        );
    
    
    ALTER TABLE table_name
       ADD CONSTRAINT sell_fk
       FOREIGN KEY (book_id)
       REFERENCES book(id);
    

答案 2 :(得分:0)

您是否已在销售表中有记录并想更新图书表中的金额? 如果是这种情况,您可以更新book.amount,如下所示:

update book  b
set b.amount = b.amount - (select count(*) from sell s where b.id = s.book_id);